首頁  >  問答  >  主體

MySQL 水平拆分之后,自动增长的ID有什么好的解决办法?

当单表的数据量过大时,会采用MySQL进行水平拆分,请问原先的自动增长的ID有什么好的解决办法?

黄舟黄舟2743 天前747

全部回覆(5)我來回復

  • 大家讲道理

    大家讲道理2017-04-17 15:06:12

    水平拆分後,同一張表的資料放在不同的庫上,無法再依賴資料庫本身的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,這個想法有點像儲存食物過冬一樣。

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-17 15:06:12

    目前我這已知的方法:
    1.修改原有的自增列,變成不自增主鍵。自己維護主鍵

    2.水平拆分為拆分已有數據,也就是說拆分出去的表的數據不會再做變化。新增的數據依然自增。 (注意不能設定自增填充空白id)

    3.做個統一演算法。自增id需要計算後寫入,而不是自動維護

    回覆
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 15:06:12

    我這邊之前也有這樣的需求。
    我是這麼處理的:把主鍵列去掉自增長,透過redis的incr產生自增序列值,插入的時候指定id的值

    回覆
    0
  • 怪我咯

    怪我咯2017-04-17 15:06:12

    1.把自增ID這個功能,用一張表與一個預存程序做成一個小模組。

    2.被分割的表,當有資料INSERT時,就呼叫這個預存程序來申請一個新ID。

    回覆
    0
  • 迷茫

    迷茫2017-04-17 15:06:12

    分錶後主鍵要自己生成最好,很多開源的主鍵生成策略演算法,比如說​​twitter的snowflake等
    如果不想改動程式的話,設定每個集群中自增ID 起始點(auto_increment_offset)以及ID 自增步長(auto_increment_increment),讓目前每個群集的起始點錯開,達到將ID 相對分段的效果來滿足全域唯一的效果。優點是實現簡單,對應用透明,缺點就是,以後如果根據id做路由的話不好擴展

    回覆
    0
  • 取消回覆