中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

雪花算法中如何使用ID生成工具

發布時間:2021-10-14 13:41:20 來源:億速云 閱讀:234 作者:iii 欄目:編程語言

本篇內容主要講解“雪花算法中如何使用ID生成工具”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“雪花算法中如何使用ID生成工具”吧!

???? 算法介紹

? 這是優化的雪花算法(雪花漂移),它生成的ID更短、速度更快。

? 支持 k8s 等容器環境自動擴容(自動注冊 WorkerId),可在單機或分布式環境生成數字型唯一ID。

? 原生支持 C#/Java/Go/Rust/C/SQL 等語言,并提供 PHP 擴展及 Python、Node.js 多線程安全調用動態庫(FFI)。

? 兼容所有雪花算法(號段模式或經典模式,大廠或小廠),將來你可做任意的升級切換。(一般無須升級,但理論上支持)

? 這是計算機歷史上最全面的雪花ID生成工具,期待你來超越????

需求來源

???? 作為架構設計的你,想要解決數據庫主鍵唯一的問題,特別是在分布式系統多數據庫中。

???? 你希望數據表主鍵用最少的存儲空間,索引速度更快,Select、Insert 和 Update 更迅速。

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

???? 如果這樣的主鍵值太長,超過前端 js Number 類型最大值,須把 Long 型轉換為 String 型,你會覺得有點沮喪。

???? 盡管 Guid 能自增,但占用空間大,索引速度慢,你不想用它。

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

???? 要在容器環境部署應用,支持水平復制、自動擴容。

???? 不想依賴 redis 的自增操作獲得連續的主鍵ID,因為連續的ID存在業務數據安全風險。

???? 你希望系統運行 100 年以上。

傳統算法問題

? 生成的ID太長。

? 瞬時并發量不夠。

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

? 不支持后補生成前序ID。

? 可能依賴外部存儲系統。

新算法特點

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

? 速度更快,是傳統雪花算法的2-5倍,0.1秒可生成50萬個(基于8代低壓i7)。

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

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

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

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

性能數據

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

連續請求量5K5W50W
傳統雪花算法0.0045s0.053s0.556s
雪花漂移算法0.0015s0.012s0.113s

???? 極致性能:500W/s~3000W/s。(所有測試數據均基于8代低壓i7計算)

如何處理時間回撥

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

???? 回撥生成的ID序號,默認靠前,也可以調整為靠后。

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

???? ID組成說明

  • 本算法生成的ID由3部分組成(沿用雪花算法定義):

  • +-------------------------+--------------+----------+

  • | 1.相對基礎時間的時間差 | 2.WorkerId | 3.序列數 |

  • +-------------------------+--------------+----------+


  • 第1部分,時間差,是生成ID時的系統時間減去 BaseTime 的總時間差(毫秒單位)。

  • 第2部分,WorkerId,是區分不同機器或不同應用的唯一ID,最大值由 WorkerIdBitLength(默認6)限定。

  • 第3部分,序列數,是每毫秒下的序列數,由參數中的 SeqBitLength(默認6)限定。

ID示例

???? 本算法生成的 ID ,是整數(占用空間最多8字節),以下是基于默認配置生成的ID:

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

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

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

長度估算

???? 每增加 1位 WorkerIdBitLength 或 SeqBitLength,生成的ID數字值將會乘以2(基礎長度可參考前一節“ID示例”),反之則除以2。

能用多久

能用多久的解釋,是指生成的ID數字,何時能增長到超過 long(有符號64位,8字節)最大值。

???? 在默認配置下,ID可用 71000 年不重復。

???? 在支持 1024 個工作節點時,ID可用 4480 年不重復。

???? 在支持 4096 個工作節點時,ID可用 1120 年不重復。

???? 參數設置

? WorkerIdBitLength,機器碼位長,決定 WorkerId 的最大值,默認值6,取值范圍 [1, 19],實際上有些語言采用 無符號 ushort (uint16) 類型接收該參數,所以最大值是16,如果是采用 有符號 short (int16),則最大值為15。

? WorkerId,機器碼,最重要參數,無默認值,必須 全局唯一,必須 程序設定,缺省條件(WorkerIdBitLength取默認值)時最大值63,理論最大值 2^WorkerIdBitLength-1(不同實現語言可能會限定在 65535 或 32767,原理同 WorkerIdBitLength 規則)。不同機器或不同應用實例 不能相同,你可通過應用程序配置該值,也可通過調用外部服務獲取值。針對自動注冊WorkerId需求,本算法提供默認實現:通過 redis 自動注冊 WorkerId 的動態庫,詳見“Tools\AutoRegisterWorkerId”。

特別提示:如果一臺服務器部署多個獨立服務,需要為每個服務指定不同的 WorkerId。

? SeqBitLength,序列數位長,默認值6,取值范圍 [3, 21](建議不小于4),決定每毫秒基礎生成的ID個數。規則要求:WorkerIdBitLength + SeqBitLength 不超過 22。

? MinSeqNumber,最小序列數,默認值5,取值范圍 [5, MaxSeqNumber],每毫秒的前5個序列數對應編號0-4是保留位,其中1-4是時間回撥相應預留位,0是手工新值預留位。

? MaxSeqNumber,最大序列數,設置范圍 [MinSeqNumber, 2^SeqBitLength-1],默認值0,真實最大序列數取最大值(2^SeqBitLength-1),不為0時,取其為真實最大序列數,一般無需設置,除非多機共享WorkerId分段生成ID(此時還要正確設置最小序列數)。

? BaseTime,基礎時間(也稱:基點時間、原點時間、紀元時間),有默認值(2020年),是毫秒時間戳(是整數,.NET是DatetTime類型),作用是:用生成ID時的系統時間與基礎時間的差值(毫秒數)作為生成ID的時間戳。基礎時間一般無需設置,如果覺得默認值太老,你可以重新設置,不過要注意,這個值以后最好不變。

常規集成

1?? 用單例模式調用。外部集成方使用更多的實例并行調用本算法,不會增加ID產出效能,因為本算法采用單線程生成ID。

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

3?? 單機多實例部署時使用不同 WorkerId。并非所有實現都支持跨進程的并發唯一,保險起見,在同一主機上部署多應用實例時,請確保各 WorkerId 唯一。

4?? 異常處理。算法會拋出所有 Exception,外部系統應 catch 異常并做好應對處理,以免引發更大的系統崩潰。

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

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

7?? 不要修改核心算法。本算法內部參數較多,邏輯較為復雜,在你尚未掌握核心邏輯時,請勿嘗試修改核心代碼且用于生產環境,除非通過大量細致、科學的測試驗證。

8?? 應用域內配置策略相同。當系統運行一段時間后,項目需要從程序指定 WorkerId 轉到自動注冊 WorkerId 時,請確保同一應用域內所有在用實例采用一致的配置策略,這不僅僅針對 WorkerId,也包含其他所有配置參數。

9?? 管理好服務器時間。雪花算法依賴系統時間,不要手工大幅度回調操作系統時間。如果一定要調整,切記:確保服務再次啟動時的系統時間大于最后一次關閉時的時間。(注:世界級或網絡級的時間同步、回撥,引起的系統時間小幅度變化,對本算法沒影響)

配置變更

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

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

???? 2.任何時候增加 WorkerIdBitLength 或 SeqBitLength,都是可以的,但是慎用 “減小”的操作,因為這可能導致在未來某天生成的 ID 與過去老配置時相同。[允許在系統運行之后增加任何一個 BitLength 值]

???? 3.如果必須減小 WorkerIdBitLength 或 SeqBitLength 其中的一項,一定要滿足一個條件:新的兩個 BitLength 之和要大于 老的值之和。[不推薦在運行之后縮小任何一個 BitLength 值]

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

自動注冊WorkerId

???? 唯一ID生成器,依賴WorkerId,當業務服務需要水平無差別復制(自動擴容)時,這就要求能自動注冊全局唯一WorkerId,然后才能生產唯一ID。

???? 本算法提供開源動態庫(go語言實現),能在容器 k8s 等容器環境下,通過 redis 自動注冊 WorkerId。

???? 通過redis注冊WorkerId,并非唯一方法。你還可以開發中心化的配置服務,各端點服務啟動時,通過中心服務獲取唯一 WorkerId。

???? 當然,如果你的服務無需自動擴容,那就不必自動注冊WorkerId,而是為它們分別設置全局唯一值。

???? 發揮你的想象力,方法還有很多。此處拋磚引玉:開發中心化的ID生成服務,由它為各端點服務(單個或批量)生成可用ID。

自動注冊流程圖

圖片鏈接:https://cache.yisu.com/upload/information/20210524/357/2830.jpg

源碼路徑:/Go/source/regworkerid/reghelper.go

動態庫下載

下載鏈接:https://github.com/yitter/IdGenerator/releases/download/reg_v1.0/regworkerid_lib_v1.0.zip

動態庫接口定義
// 注冊一個 WorkerId,會先注銷所有本機已注冊的記錄
// ip: redis 服務器地址
// port: redis 端口
// password: redis 訪問密碼,可為空字符串“”
// maxWorkerId: 最大 WorkerId
extern GoInt32 RegisterOne(char* ip, GoInt32 port, char* password, GoInt32 maxWorkerId);

// 注銷本機已注冊的 WorkerId
extern void UnRegister();

// 檢查本地WorkerId是否有效(0-有效,其它-無效)
extern GoInt32 Validate(GoInt32 workerId);

已實現的語言

語言github
???? C#查看示例
???? Java查看示例
???? Go查看示例
???? Rust查看示例
???? C查看示例
???? C (PHP擴展)查看示例
???? V查看示例
???? D查看示例

到此,相信大家對“雪花算法中如何使用ID生成工具”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

莱西市| 三河市| 千阳县| 赤城县| 东丽区| 固原市| 郴州市| 宿州市| 漾濞| 祁东县| 万荣县| 大姚县| 临沭县| 台南市| 合肥市| 宜宾县| 五峰| 东丰县| 青州市| 资兴市| 剑河县| 兴海县| 深水埗区| 石家庄市| 乐清市| 盐城市| 上饶市| 广昌县| 乌拉特中旗| 安国市| 佛坪县| 红原县| 罗田县| 汤阴县| 青冈县| 哈密市| 叙永县| 锡林郭勒盟| 富蕴县| 大冶市| 兰州市|