九種主流的分佈式 ID 生成策略

前言

構建分佈式系統時,如何對數據進行唯一標識也是一個至關重要的設計。不僅要符合 B-tree 數據結構以維持查詢性能,還要考慮唯一標識的連續性會不會影響系統安全性。在分庫分表的情況下,還要避免唯一標識重複且高效等等需要考慮的點。

爲此,市場就出現了很多分佈式 ID 生成方案。本文將詳細介紹九種主流的分佈式 ID 生成策略供大家參考使用。

1、UUID

UUID(Universally Unique Identifier) 是基於當前時間計數器硬件標識(通常爲無線網卡的 MAC 地址)等數據計算生成的。

示例代碼

JDK 提供了 UUID 生成工具,示例代碼如下:

存在的問題

UUID 完全可以滿足分佈式唯一標識,但是在實際應用過程中一般不採用,有幾個原因:

  1. 存儲成本高:UUID 太長,16 字節 128 位,以 36 長度的字符串表示,很多場景不適用。

  2. 信息不安全:基於 MAC 地址生成的 UUID 算法會暴露 MAC 地址,曾經梅麗莎病毒的製造者就是根據 UUID 尋找的。

  3. 不符合 MySQL 主鍵要求:MySQL 官方有明確的建議,主鍵要儘量越短越好,因爲太長對 MySQL 索引不利。

(如果 UUID 作爲數據庫主鍵,在 InnoDB 引擎下,UUID 的無序性可能會引起數據位置頻繁變動,嚴重影響性能。)

2、數據庫自增 ID

利用 MySQL 自增的 ID,可以達到數據唯一標識。

但是分庫分表後不能保證整體的 ID 唯一。爲了避免這種情況,有以下兩種方式可以解決該問題。

全局主鍵表

創建全局主鍵表維護唯一標識,作爲 ID 的輸出源可以保證整體 ID 的唯一。

主鍵表示例:

當業務獲取唯一標識時,執行下方 SQL 獲取,然後添加到某個分表中。

ID 自增步長設置

通過設置 MySQL 主鍵自增步長,讓分佈在不同實例的表數據 ID 做到不重複,從而保證整體的唯一。

如下,可以設置實例 1 步長爲 1,實例 1 步長爲 2。

顯然,這種方式的擴展性會是一個非常大的問題。

3、號段模式

號段模式介紹

號段模式是當下分佈式 ID 生成器的主流實現方式之一。其原理如下:

  1. 號段模式每次從數據庫取出一個號段範圍,加載到服務內存中。避免每次生成 ID 都去訪問數據庫

  2. 當號段 ID 用完,再次向數據庫申請新號段,對 max_id 字段做一次 update 操作,新的號段範圍是 (max_id ,max_id +step]。

  3. 由於多業務端可能同時操作,所以採用版本號 version 樂觀鎖方式更新。

表結構如下:

優缺點

這種分佈式 ID 生成方式不強依賴於數據庫,不會頻繁的訪問數據庫,對數據庫的壓力小很多

但同樣也會存在一些缺點,比如:服務器重啓,單點故障會造成 ID 不連續

4、Redis INCR

作爲共享內存,可以通過 Redis 的 INCR 命令來生成全局唯一 ID。

簡單的代碼示例

Redis 也有對應的缺點:ID 生成的持久化問題,如果 Redis 宕機了怎麼進行恢復是開發人員需要考慮的。

5、雪花算法

Snowflake,雪花算法是有 Twitter 開源的分佈式 ID 生成算法,以劃分命名空間的方式將 64bit 位分割成了多個部分,每個部分都有具體的不同含義,在 Java 中 64Bit 位的整數是 Long 類型,所以在 Java 中 Snowflake 算法生成的 ID 就是 long 來存儲的。具體如下:

雪花算法強依賴機器時鐘如果機器上時鐘回撥,會導致重複。通常通過記錄最後使用時間處理該問題。

6、美團 (Leaf)

美團點評分佈式 ID 生成系統。支持號段模式和 snowflake 算法模式,可以切換使用。

開源項目鏈接:

https://github.com/Meituan-Dianping/Leaf

Leaf 詳細介紹:

https://tech.meituan.com/2017/04/21/mt-leaf.html

7、百度 (Uidgenerator)

UidGenerator 是百度開源的 Java 語言實現,基於 Snowflake 算法的。克服了雪花算法的併發限制,單個實例的 QPS 能超過 6000000。需要的環境:JDK8+,MySQL(用於分配 WorkerId)。

源碼地址:

https://github.com/baidu/uid-generator

中文文檔地址:

https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

8、滴滴 (TinyID)

Tinyid 是滴滴基於美團(Leaf)的號段模式基礎上升級而來,不僅支持了數據庫多主節點模式,還提供了 tinyid-client 客戶端的接入方式,使用起來更加方便。

開源項目鏈接:

https://github.com/didi/tinyid

總結比較

SzA8PN

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Q4-oXXGUMJrxX5EEV2F77w