84669 人學習
152542 人學習
20005 人學習
5487 人學習
7821 人學習
359900 人學習
3350 人學習
180660 人學習
48569 人學習
18603 人學習
40936 人學習
1549 人學習
1183 人學習
32909 人學習
当单表的数据量过大时,会采用MySQL进行水平拆分,请问原先的自动增长的ID有什么好的解决办法?
人生最曼妙的风景,竟是内心的淡定与从容!
水平拆分後,同一張表的資料放在不同的庫上,無法再依賴資料庫本身的auto_increment實現ID的唯一性,多個庫之間產生的ID會造成衝突。 因此ID不應該由資料庫來分配,那麼應該由什麼來分配,我覺得要分兩種情況:
如果應用程式是透過資料庫中間件來存取後台的MySQL,那麼ID應該由中間件來產生
如果沒有中間件,ID由應用程式產生
但無論是應用或中間件,應用肯定會是多個的(多個客戶端),而中間件,中間件一般也不會部署一個單實例,這樣會有單點問題(single point of failure), 中介軟體在生產環境下,是叢集部署的。
那麼問題就清晰明了很多了,無論是上面哪一種情況,實際上你需要的是一個全局的,global的ID產生器。
全域的global產生器有很多種方式可以實作
從公用資料庫取ID
把ID產生策略放在zookeeper叢集上,去zookeeper叢集上取全域ID
基本的策略就是這樣了。還有一點小細節。
全域ID最好以表來劃分,一個表對應一個全域ID上下文,不同的表去不同的全域ID上下文取。
另外一個,無論是中間件也好,應用也好,取全域ID時不要每次只取一個,那樣性能太低了,更好的方式是每次取一段ID,例如應用1取到了1-50這段ID,那麼它就可以在這50個ID用完之前,不再需要去取ID;應用2也去取ID,那麼它會取到51-100這段ID,這個想法有點像儲存食物過冬一樣。
目前我這已知的方法:1.修改原有的自增列,變成不自增主鍵。自己維護主鍵
2.水平拆分為拆分已有數據,也就是說拆分出去的表的數據不會再做變化。新增的數據依然自增。 (注意不能設定自增填充空白id)
3.做個統一演算法。自增id需要計算後寫入,而不是自動維護
我這邊之前也有這樣的需求。 我是這麼處理的:把主鍵列去掉自增長,透過redis的incr產生自增序列值,插入的時候指定id的值
1.把自增ID這個功能,用一張表與一個預存程序做成一個小模組。
2.被分割的表,當有資料INSERT時,就呼叫這個預存程序來申請一個新ID。
分錶後主鍵要自己生成最好,很多開源的主鍵生成策略演算法,比如說twitter的snowflake等如果不想改動程式的話,設定每個集群中自增ID 起始點(auto_increment_offset)以及ID 自增步長(auto_increment_increment),讓目前每個群集的起始點錯開,達到將ID 相對分段的效果來滿足全域唯一的效果。優點是實現簡單,對應用透明,缺點就是,以後如果根據id做路由的話不好擴展
水平拆分後,同一張表的資料放在不同的庫上,無法再依賴資料庫本身的auto_increment實現ID的唯一性,多個庫之間產生的ID會造成衝突。
因此ID不應該由資料庫來分配,那麼應該由什麼來分配,我覺得要分兩種情況:
如果應用程式是透過資料庫中間件來存取後台的MySQL,那麼ID應該由中間件來產生
如果沒有中間件,ID由應用程式產生
但無論是應用或中間件,應用肯定會是多個的(多個客戶端),而中間件,中間件一般也不會部署一個單實例,這樣會有單點問題(single point of failure), 中介軟體在生產環境下,是叢集部署的。
那麼問題就清晰明了很多了,無論是上面哪一種情況,實際上你需要的是一個全局的,global的ID產生器。
全域的global產生器有很多種方式可以實作
從公用資料庫取ID
把ID產生策略放在zookeeper叢集上,去zookeeper叢集上取全域ID
基本的策略就是這樣了。還有一點小細節。
全域ID最好以表來劃分,一個表對應一個全域ID上下文,不同的表去不同的全域ID上下文取。
另外一個,無論是中間件也好,應用也好,取全域ID時不要每次只取一個,那樣性能太低了,更好的方式是每次取一段ID,例如應用1取到了1-50這段ID,那麼它就可以在這50個ID用完之前,不再需要去取ID;應用2也去取ID,那麼它會取到51-100這段ID,這個想法有點像儲存食物過冬一樣。
目前我這已知的方法:
1.修改原有的自增列,變成不自增主鍵。自己維護主鍵
2.水平拆分為拆分已有數據,也就是說拆分出去的表的數據不會再做變化。新增的數據依然自增。 (注意不能設定自增填充空白id)
3.做個統一演算法。自增id需要計算後寫入,而不是自動維護
我這邊之前也有這樣的需求。
我是這麼處理的:把主鍵列去掉自增長,透過redis的incr產生自增序列值,插入的時候指定id的值
1.把自增ID這個功能,用一張表與一個預存程序做成一個小模組。
2.被分割的表,當有資料INSERT時,就呼叫這個預存程序來申請一個新ID。
分錶後主鍵要自己生成最好,很多開源的主鍵生成策略演算法,比如說twitter的snowflake等
如果不想改動程式的話,設定每個集群中自增ID 起始點(auto_increment_offset)以及ID 自增步長(auto_increment_increment),讓目前每個群集的起始點錯開,達到將ID 相對分段的效果來滿足全域唯一的效果。優點是實現簡單,對應用透明,缺點就是,以後如果根據id做路由的話不好擴展