細聊分佈式ID生成方法-2

業內方案簡介

1. UUID方案

優點:

能夠保證獨立性,程序可以在不同的數據庫間遷移,效果不受影響。

保證生成的ID不僅是表獨立的,而且是庫獨立的,這點在你想切分數據庫的時候尤爲重要。

缺點:

1. 性能爲題:UUID太長,通常以36長度的字符串表示,對MySQL索引不利:如果作爲數據庫主鍵,在InnoDB引擎下,UUID的無序性可能會引起數據位置頻繁變動,嚴重影響性能

2. UUID無業務含義:很多需要ID能標識業務含義的地方不使用

3.不滿足遞增要求

2. snowflake方案

snowflake是twitter開源的分佈式ID生成系統。 Twitter每秒有數十萬條消息的請求,每條消息都必須分配一條唯一的id,這些id還需要一些大致的順序(方便客戶端排序),並且在分佈式系統中不同機器產生的id必須不同。

snowflake的結構如下(每部分用-分開):

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 – 000000000000

第一位爲未使用,接下來的41位爲毫秒級時間(41位的長度可以使用69年),然後是5位datacenterId和5位workerId(10位的長度最多支持部署1024個節點) ,最後12位是毫秒內的計數(12位的計數順序號支持每個節點每毫秒產生4096個ID序號)

一共加起來剛好64位,爲一個Long型。(轉換成字符串長度爲18)

snowflake生成的ID整體上按照時間自增排序,並且整個分佈式系統內不會產生ID碰撞(由datacenter和workerId作區分),並且效率較高。snowflake的缺點是:

  1. 強依賴時鐘,如果主機時間回撥,則會造成重複ID,會產生
  2. ID雖然有序,但是不連續

snowflake現在有較好的改良方案,比如美團點評開源的分佈式ID框架:leaf,通過使用ZooKeeper解決了時鐘依賴問題。

詳細見源碼:SnowflakeIdWorker 

3. 基於數據庫方案

利用數據庫生成ID是最常見的方案。能夠確保ID全數據庫唯一。其優缺點如下:

優點:

  • 非常簡單,利用現有數據庫系統的功能實現,成本小,有DBA專業維護。

  • ID號單調自增,可以實現一些對ID有特殊要求的業務。

缺點:

  • 不同數據庫語法和實現不同,數據庫遷移的時候或多數據庫版本支持的時候需要處理。

  • 在單個數據庫或讀寫分離或一主多從的情況下,只有一個主庫可以生成。有單點故障的風險。
  • 在性能達不到要求的情況下,比較難於擴展。
  • 如果涉及多個系統需要合併或者數據遷移會比較麻煩。
  • 分表分庫的時候會有麻煩。

4.其他方案簡介

通過Redis生成ID(主要通過redis的自增函數)、ZooKeeper生成ID、MongoDB的ObjectID等均可實現唯一性的要求

三、我們在實際應用中經歷的方案

1. 方案簡介

 實際業務中,除了分佈式ID全局唯一之外,還有是否趨勢/連續遞增的要求。根據具體業務需求的不同,有兩種可選方案。

一是隻保證全局唯一,不保證連續遞增。二是既保證全局唯一,又保證連續遞增。

2. 基於ZooKeeper和本地緩存的方案

基於zookeeper分佈式ID實現方案有很多種,本方案只使用ZooKeeper作爲分段節點協調工具。每臺服務器首先從zookeeper緩存一段,如1-1000的id,

此時zk上保存最大值1000,每次獲取的時候都會進行判斷,如果id<=1000,則更新本地的當前值,如果爲1001,則會將zk上的最大值更新至2000,本地緩存

段更新爲1001-2000,更新的時候使用curator的分佈式鎖來實現。

由於ID是從本機獲取,因此本方案的優點是性能非常好。缺點是如果多主機負載均衡,則會出現不連續的id,當然將遞增區段設置爲1也能保證連續的id,


3.利用zk的永久自增節點策略實現持續遞增ID

使用zk的永久sequence策略創建節點,並獲取返回值,然後刪除前一個節點,這樣既防止zk服務器存在過多的節點,又提高了效率;節點刪除採用線程池來統一處理,提高響應速度

優點:能創建連續遞增的ID,又能降低ZK消耗。

測試結果如下,生成10000個ID消耗=9443ms(兩個線程耗時較長者),  平均每個ID=0.9ms

這還只是單zk連接的情況下,如果使用連接池來維護多個zk的鏈接,效率將成倍的提升


感謝分享,原鏈接:

https://blog.csdn.net/m0_37041378/article/details/78125747



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章