開源一個比雪花算法更好用的ID生成算法(雪花漂移)

比雪花算法更好用的ID生成算法(單機或分佈式惟一ID)

💎 算法介紹

一個全新的雪花漂移算法,生成的ID更短、速度更快。前端

核心在於縮短ID長度的同時,具備極高瞬時併發處理量(保守值 50W/0.1s)。git

原生支持 C#/Java/Go/Rust/C 等語言,並由 Rust 提供 PHP、Python、Node.js、Ruby 等語言多線程安全調用庫(FFI)。若是你的應用有語言開發,基於本算法提供的邏輯實現,集成會更簡單,邏輯會更一致。github

支持 k8s 等容器化部署,自動註冊 WorkerId。redis

可在單機或分佈式環境中生成惟一ID。算法

💎 技術支持

開源地址1:https://gitee.com/yitter/idgenerator數據庫

開源地址2:https://github.com/yitter/idgenerator緩存

QQ羣:646049993安全

需求來源

💧 做爲架構設計的你,想要解決數據庫主鍵惟一的問題,特別是在分佈式系統多數據庫的時候。服務器

💧 你但願這個主鍵是用最少的存儲空間,索引速度更快,Select、Insert 和 Update 更迅速。多線程

💧 你要考慮在分庫分表(合庫合表)時,主鍵值可直接使用,並能反映業務時序。

💧 若是這樣的主鍵值太長,超過前端 JS Number 類型最大值,須把 Long 型轉換爲 String 型,你會以爲有點沮喪。

💧 儘管 Guid 能自增,但佔用空間大,索引速度慢,你也不想用它。

💧 應用實例可能超過50個,每一個併發請求可達10W/s。

💧 在容器環境部署應用(水平擴展、自動伸縮)。

💧 不想依賴 redis 的自增操做。

💧 你但願系統運行 100 年以上。

傳統算法問題

❌ 生成的ID太長。

❌ 瞬時併發量不夠。

❌ 不能解決時間回撥問題。

❌ 不支持後補生成前序ID。

❌ 依賴外部存儲系統。

新算法特色

整形數字,隨時間單調遞增(不必定連續),長度更短,用50年都不會超過 js Number類型最大值。(默認配置 WorkerId 是6bit,自增數是6bit)

速度更快,是傳統雪花算法的2-5倍,0.1秒可生成50萬個。(i7筆記本,默認算法配置6bit+6bit)

支持時間回撥處理。好比服務器時間回撥1秒,本算法能自動適應生成臨界時間的惟一ID。

支持手工插入新ID。當業務須要在歷史時間生成新ID時,用本算法的預留位能生成5000個每秒。

漂移時能外發通知事件。讓調用方確切知道算法漂移記錄,Log併發調用量。

不依賴任何外部緩存和數據庫。(k8s環境下自動註冊 WorkerId 的動態庫依賴 redis)

基礎功能,開箱即用,無需配置文件、數據庫鏈接等。

性能數據

(參數:10位自增序列,1000次漂移最大值)

連續請求量 5K 5W 50W
傳統雪花算法 0.0045s 0.053s 0.556s
雪花漂移算法 0.0015s 0.012s 0.113s

效果

🟣 js Number 類型最大數值:9007199254740992,本算法在保持併發性能(5W+/0.01s)和最大64個 WorkerId(6bit)的同時,能用70年纔到 js Number Max 值。

🟣 增長WorkerId位數到8bit(256節點)時,15年達到 js Number Max 值。

🟣 極致性能:500W/s~3000W/s。(全部測試數據均基於8代低壓i7計算。)

💎 生成的ID

默認配置:

WorkerIdBitLength = 6
SeqBitLength = 6

ID示例(基於默認配置):

129053495681099        (本算法運行1年)
387750301904971        (運行3年)
646093214093387        (運行5年)
1292658282840139       (運行10年)
9007199254740992       (js Number 最大值)
165399880288699493     (普通雪花算法生成的ID)

本算法生成的 ID 值,是 js Number 最大值的 1%-10%,是普通雪花算法值的千分之一,而計算能力卻超過普通雪花算法。

適用範圍

🔷小型、中型、大型須要全局惟一Id(不用Guid)的項目。

🔷 分佈式項目。

🔷不想將 Long 型轉 String 給前端用的項目。(若前端支持bigint,則可不轉類型)

如何處理時間回撥

🔶 當發生系統時間回撥時,算法採用過去時序的預留序數生成新的ID。

🔶 默認每秒生成100個(速度可調整)。

🔶 回撥生成的ID序號,默認靠前,也能夠調整爲靠後。

🔶 容許時間回撥至本算法預設基數(參數可調)。

能用多久

🔵 在默認配置下,ID可用 71000 年不重複。

🔵 在支持 1024 個工做節點時,ID可用 4480 年不重複。

🔵 在支持 4096 個工做節點時,ID可用 1120 年不重複。

🔵 以上全部工做節點,均擁有 50W/0.1s 瞬時處理速度。

默認配置

💍 WorkerIdBitLength=6,能支持64個 WorkerId,編號0~63。

💍 可經過減小 WorkerIdBitLength 到1~4(爲4時最大支持WorkerId爲2^4=16個),以減小Id長度。

💍 SeqBitLength=6,能支持每秒併發5W請求時,平均處理速度不超過 0.005 s。(不一樣語言略有差異,最高性能不超過0.002s,平均不超過0.005s)

💍 可經過增長 SeqBitLength,支持更高的每秒併發數。默認配置能很高效地支持每秒 5W 併發請求,若要求更高,可適當增長 SeqBitLength 到 8~16,但這將增長Id長度。

集成建議

💎 常規集成

1️⃣ 用單例模式調用。外部集成方使用更多的實例並行調用本算法,不會增長ID產出效能,由於本算法採用單線程模式生成ID。

2️⃣ 指定惟一的 WorkerId。必須由外部系統確保 WorkerId 的全局惟一性,並賦值給本算法入口方法。

3️⃣ 單機多實例部署時使用不一樣 WorkerId。並不是全部實現都支持跨進程的併發惟一,保險起見,在同一主機上部署多應用實例時,請確保各 WorkerId 惟一。

4️⃣ 異常處理。算法會拋出全部 Exception,外部系統應 catch 異常並作好應對處理,以避免引起更大的系統崩潰。

5️⃣ 認真理解 IdGeneratorOptions 的定義,這對集成和使用本算法有幫助。

6️⃣ 使用雪花漂移算法。雖然代碼裏包含了傳統雪花算法的定義,而且你能夠在入口處指定(Method=2)來啓用傳統算法,但仍建議你使用雪花漂移算法(Method=1,默認的),畢竟它具備更好的伸縮力和更高的性能。

7️⃣ 不要修改核心算法。本算法內部參數較多,邏輯較爲複雜,在你還沒有掌握核心邏輯時,請勿嘗試修改核心代碼且用於生產環境,除非經過大量細緻、科學的測試驗證。

💎 自動註冊WorkerId

🔍 惟一ID生成器,依賴WorkerId,當業務服務須要水平自動化複製時,就要求它能自動化註冊全局惟一WorkerId,而後各個容器化的無差異部署的業務服務,才能根據它生產惟一ID。

🔍 本算法提供一個開源的動態庫(go語言實現),能在容器 k8s(或其它容器化集羣) 環境下,經過 redis 自動註冊 WorkerId。動態庫提供的C接口方法有:

// 註冊一個新的WorkerId
extern __declspec(dllexport) GoInt RegisterWorkerId(char* ip, GoInt port, char* password, GoInt maxWorkerId);

// 註銷WorkerId
extern __declspec(dllexport) void UnRegisterWorkerId();

// 檢查本地WorkerId是否有效
extern __declspec(dllexport) GoUint8 ValidateLocalWorkerId(GoInt workerId);

redis做用

🔎 只用於註冊 WorkerId ,不用於生產 ID。

🔎 若是手工指定 WorkerId,便可不依賴 redis。

其它分佈式集成

🟢1.可增長 WorkerIdBitLength 到最大20,支持 1,048,576 個節點,且不影響上述併發性能。[算法支持]

🟢2.採用中心化 IdGenerator 集羣,生成可用 Id 列表,存入 Redis 隊列供節點消費。此時64箇中心化節點數足夠大型互聯網項目使用。[需集成方擴展實現]

🟢3.以上2條二選一便可,採用方法2通常是由於不想增長最終 ID 長度,但節點數超過64個。

🟢4.任何加大 WorkerIdBitLength 或 SeqBitLength 的設置,均可能會增長 ID 的長度。

💎 配置變動

配置變動指是系統運行一段時間後,再變動運行參數(IdGeneratorOptions選項值),請注意:

🔴 1.最重要的一條原則是:BaseTime 只能往前(比老值更小、距離如今更遠)賦值,緣由是日後賦值極大可能產生相同的時間戳。[不推薦在系統運行以後調整 BaseTime]

🔴 2.任什麼時候候增長 WorkerIdBitLength 或 SeqBitLength,都是能夠的,可是慎用 「減少」的操做,由於這可能致使在將來某天生成的 ID 與過去老配置時相同。[容許在系統運行以後增長任何一個 BitLength 值]

🔴 3.若是必須減少 WorkerIdBitLength 或 SeqBitLength 其中的一項,必定要知足一個條件:新的兩個 BitLength 之和要大於 老的值之和。[不推薦在運行以後縮小任何一個 BitLength 值]

🔴 4.上述3條規則,並未在本算法內作邏輯控制,集成方應根據上述規則作好影響評估,確認無誤後,再實施配置變動。

💎💎 代碼示例

🌲🏳️‍🌈 C#:查看示例

🌲🏳️‍🌈 Java:查看示例

🌲🏳️‍🌈 Go:查看示例

🌲🏳️‍🌈 Rust:查看示例

🌲🏳️‍🌈 C:查看示例

相關文章
相關標籤/搜索