微服務之唯一ID生成策略

襄垣發表於2019-08-01

資料庫自增ID

最簡單的實現方式是使用資料庫的id自增策略,如 MySQLauto_increment。如果兩臺資料庫分別設定不同步長,可以生成不重複ID,從而實現高可用。

優點

實現簡單,容易理解,單調自增,絕對有序。

缺點

  1. 強依賴DB,當DB異常時整個系統不可用,屬於致命問題。
  2. ID發號效能瓶頸限制在單臺MySQL的讀寫效能。

UUID系列

結合機器的網路卡、當地時間、一個隨記數來生成UUID。存在一些UUID的變種也是不錯的實現。

優點

本地生成,生成簡單,效能非常好,高可用。

缺點

  1. 長度過長,不易儲存,無序不可讀,查詢效率低。
  2. 資訊不安全,基於MAC地址生成UUID的演算法可能會造成MAC地址洩露,這個漏洞曾被用於尋找梅麗莎病毒的製作者位置。
  3. UUID的無序性可能會引起資料位置頻繁變動,嚴重影響效能。

Redis實現ID

Redis的所有命令操作都是單執行緒的,本身提供像 incrincreby 這樣的自增原子命令,所以能保證生成的 ID 肯定是唯一有序的。

舉例,使用 Redis 來生成每天從0開始的流水號。比如訂單號 = 日期 + 當日自增長號。可以每天在 Redis 中生成一個 Key ,使用 INCR 進行累加。

優點

  1. 靈活方便,且效能優於資料庫。
  2. 數字ID天然排序,通過合理設計可以得到更具有表達能力的ID。

缺點

  1. 引入Redis,編碼和配置的工作量比較大。
  2. 如果ID是連續的,惡意使用者的扒取工作就非常容易做了,直接按照順序下載指定URL即可;如果是訂單號就更危險了,競對可以直接知道我們一天的單量。所以在一些應用場景下,會需要ID無規則、不規則。

Twitter的snowflake演算法生成ID

詳細可以參照 github.com/twitter/sno…

優點

  1. 時間有序,毫秒數在高位,自增序列在低位,整個ID都是趨勢遞增的。
  2. 不依賴資料庫等第三方系統,以服務的方式部署,穩定性更高,生成ID的效能也是非常高的。
  3. 可以根據自身業務特性分配bit位,非常靈活。
  4. Long型。

缺點

依賴於機器的時鐘,如果機器上時鐘回撥,會導致發號重複或者服務會處於不可用狀態。

百度UidGenerator

百度基於snowflake的一種實現,參見 github.com/baidu/uid-g…

優點

同上 Twitter的snowflake演算法生成ID

缺點

需要MySQL(內建WorkerID分配器, 啟動階段通過DB進行分配; 如自定義實現, 則DB非必選依賴)

美團Leaf

參見 tech.meituan.com/2017/04/21/…

優點

  1. 高可用容災。
  2. ID號碼是趨勢遞增的8byte的64位數字,滿足資料庫儲存的主鍵要求。

缺點

  1. DB當機會造成整個系統不可用。
  2. 比較複雜。

MongoDB的ObjectId

通過“時間+機器碼+pid+inc”共12個位元組,通過4+3+2+3的方式最終標識成一個24長度的十六進位制字元。

優點

  1. 輕量型的,不同的機器都能用全域性唯一的同種方法方便地生成它。
  2. 本地生成,含時間戳,有序,成本低。
  3. 安全性高。
  4. 比較短,24位,比如掘金的ID,juejin.im/editor/post…

缺點

  1. 比較長,難於記憶。
  2. 使用機器ID和程式ID,64位Long無法儲存,只能生成特殊ObjectId物件。

自己程式設計實現雪花演算法

參照 Twitter的snowflake演算法生成ID,參考MongoDBObjectId的生成策略,使用類似機器ID,程式ID來保證唯一性。

相關文章