開(kāi)源一個(gè)c# 新的雪花算法
介紹
用一種全新的雪花漂移算法(以下簡(jiǎn)稱(chēng)本算法),讓ID更短、生成速度更快。
核心在于縮短ID長(zhǎng)度的同時(shí),還能保持極高并發(fā)處理量(50W/0.1s),且具有很強(qiáng)配置能力。
需求來(lái)源
1.作為架構(gòu)設(shè)計(jì)的你,想要解決數(shù)據(jù)庫(kù)主鍵唯一的問(wèn)題,特別是在分布式系統(tǒng)多數(shù)據(jù)庫(kù)的時(shí)候。
2.你希望這個(gè)主鍵是用最少的存儲(chǔ)空間,索引速度更快,Select、Insert 和 Update 更迅速。
3.你要考慮在分庫(kù)分表(合庫(kù)合表)的時(shí)候,主鍵值可直接使用,并能反映業(yè)務(wù)時(shí)序。
4.如果這樣的主鍵值太長(zhǎng),超過(guò)前端 JS Number 類(lèi)型最大值,須把 Long 型轉(zhuǎn)換為 String 型,你會(huì)覺(jué)得有點(diǎn)沮喪。
5.哪怕 Guid 能自增,但占用空間大,這也不是你想要的。
6.你希望系統(tǒng)能運(yùn)行 100 年以上。
傳統(tǒng)算法問(wèn)題
1.生成的ID太長(zhǎng)。
2.并發(fā)量不夠。
3.不能解決時(shí)間回?fù)軉?wèn)題。
4.不支持后補(bǔ)生成前序ID。
5.依賴(lài)外部緩存系統(tǒng)。
新算法特點(diǎn)
1.整形數(shù)字,隨時(shí)間單調(diào)遞增(不一定連續(xù)),長(zhǎng)度更短,用50年都不會(huì)超過(guò) js Number類(lèi)型最大值。(默認(rèn)配置 WorkerId 是6bit,自增數(shù)是6bit)
2.速度更快,是傳統(tǒng)雪花算法的2-5倍,0.1秒可生成50萬(wàn)個(gè)。(i7筆記本,默認(rèn)算法配置6bit+6bit)
3.支持時(shí)間回?fù)芴幚?。比如服?wù)器時(shí)間回?fù)?秒,本算法能自動(dòng)適應(yīng)生成臨界時(shí)間的唯一ID。
4.支持手工插入新ID。當(dāng)業(yè)務(wù)需要在歷史時(shí)間生成新ID時(shí),用本算法的預(yù)留位能生成5000個(gè)每秒。
5.漂移時(shí)能外發(fā)通知事件。讓調(diào)用方確切知道算法漂移記錄,Log并發(fā)調(diào)用量。
6.不依賴(lài)任何外部緩存和數(shù)據(jù)庫(kù)。(但 WorkerId 必須由外部指定)
性能數(shù)據(jù)
(參數(shù):10位自增序列,1000次漂移最大值)
連續(xù)請(qǐng)求量 | 5K | 5W | 50W |
---|---|---|---|
傳統(tǒng)雪花算法 | 0.0045s | 0.053s | 0.556s |
雪花漂移算法 | 0.0015s | 0.012s | 0.113s |
效果
1.js Number 類(lèi)型最大數(shù)值:9007199254740992,本算法在保持并發(fā)性能(5W+/0.01s)和最大64個(gè) WorkerId(6bit)的同時(shí),能用70年才到 js Number Max 值。
2.增加WorkerId位數(shù)到8bit(128節(jié)點(diǎn))時(shí),15年達(dá)到 js Number Max 值。
3.極致性能:500W/1s。
4.所有測(cè)試數(shù)據(jù)均基于8代低壓i7計(jì)算。
“我”是什么
1.本算法是一個(gè)類(lèi)庫(kù),它基于 net standard2.0 基礎(chǔ)庫(kù),不依賴(lài)任何第三方組件。
2.本算法不依賴(lài)任何外部數(shù)據(jù)系統(tǒng)(除了要被指定 WorkerId 之外)。
適用范圍
1.小型、中型、大型需要全局唯一Id(不用Guid)的項(xiàng)目。
2.分布式項(xiàng)目。
3.不想將 Long 型轉(zhuǎn) String 給前端用的項(xiàng)目。(若前端支持bigint,則可不轉(zhuǎn)類(lèi)型)
如何處理時(shí)間回?fù)?br /> 1.當(dāng)發(fā)生系統(tǒng)時(shí)間回?fù)艿臅r(shí)候,算法采用過(guò)去時(shí)序的預(yù)留序數(shù)生成新的ID。
2.默認(rèn)每秒生成100個(gè)(速度可調(diào)整)。
3.回?fù)苌傻腎D序號(hào),默認(rèn)靠前,也可以調(diào)整為靠后。
4.允許時(shí)間回?fù)苤帘舅惴A(yù)設(shè)基數(shù)(參數(shù)可調(diào))。
能用多久
1.在默認(rèn)配置下,ID可用 71000 年不重復(fù)。
2.在支持 1024 個(gè)工作節(jié)點(diǎn)時(shí),ID可用 4480 年不重復(fù)。
3.在支持 4096 個(gè)工作節(jié)點(diǎn)時(shí),ID可用 1120 年不重復(fù)。
4.以上所有工作節(jié)點(diǎn),均擁有 50W/0.1s 最大處理速度。
★★集成建議★★
常規(guī)集成
1.用單例模式調(diào)用。外部集成方使用更多的實(shí)例并行調(diào)用本算法,不會(huì)增加ID產(chǎn)出效能,因?yàn)楸舅惴ú捎脝尉€程模式生成ID。
2.指定唯一的 WorkerId。必須由外部系統(tǒng)確保 WorkerId 的全局唯一性,并賦值給本算法入口方法。
3.異常處理。本算法內(nèi)部會(huì)拋出所有Exception,外部系統(tǒng) catch 相關(guān)信息并做好應(yīng)對(duì)處理,以免引發(fā)更大的系統(tǒng)崩潰。
4.認(rèn)真理解 IdGeneratorOptions 的定義,這對(duì)集成和使用本算法有幫助。
5.訂閱ID異步通知。IIdGenerator.GenIdActionAsync 是一個(gè)可以向外部系統(tǒng)異步發(fā)送ID生成消息的事件,它包含的消息類(lèi)型有"漂移開(kāi)始、漂移結(jié)束、時(shí)間回?fù)?,具體參考 Yitter.IdGenTest 的 Program.cs 啟動(dòng)代碼。不過(guò)訂閱ID異步通知會(huì)有細(xì)微的性能損失。
6.同步或同步調(diào)用。你可在外部系統(tǒng)的異步(async標(biāo)記)方法中調(diào)用本算法,同步調(diào)用同樣沒(méi)問(wèn)題。
7.使用雪花漂移算法。雖然代碼里包含了傳統(tǒng)雪花算法的定義,并且你可以在入口處指定(Method=2)來(lái)啟用傳統(tǒng)算法,但仍建議你使用雪花漂移算法(Method=1,默認(rèn)的),畢竟它具有更好的伸縮力和更高的性能。
8.輕易不要修改核心算法。本算法內(nèi)部參數(shù)較多,邏輯較為復(fù)雜,在你尚未掌握核心邏輯時(shí),請(qǐng)勿嘗試修改核心代碼且用于生產(chǎn)環(huán)境,除非通過(guò)大量細(xì)致、科學(xué)的測(cè)試驗(yàn)證。
大型分布式集成
1.可擴(kuò)大 WorkerIdBitLength 到最大20,支持 1,048,576 個(gè)節(jié)點(diǎn),且不影響上述并發(fā)性能(50W/0.1s)。[算法支持]
2.采用中心化 IdGenerator 集群,給節(jié)點(diǎn)生成可用 Id 列表,存入 Redis 隊(duì)列供節(jié)點(diǎn)消費(fèi)。此時(shí)64個(gè)中心化節(jié)點(diǎn)數(shù)足夠大型互聯(lián)網(wǎng)項(xiàng)目使用。[需集成方擴(kuò)展實(shí)現(xiàn)]
3.以上2條二選一即可,采用方法2一般是因?yàn)椴幌朐黾幼罱K ID 長(zhǎng)度,但節(jié)點(diǎn)數(shù)超過(guò)64個(gè)。
4.任何加大 WorkerIdBitLength 或 SeqBitLength 的設(shè)置,都可能會(huì)增加 ID 的長(zhǎng)度。
配置變更
配置變更指是系統(tǒng)運(yùn)行一段時(shí)間后,再變更運(yùn)行參數(shù)(IdGeneratorOptions選項(xiàng)值),請(qǐng)注意:
1.最重要的一條原則是:StartTime 只能往前(比老值更小、距離現(xiàn)在更遠(yuǎn))賦值,原因是往后賦值極大可能產(chǎn)生相同的時(shí)間戳。[不推薦在系統(tǒng)運(yùn)行之后調(diào)整 StartTime]
2.任何時(shí)候增加 WorkerIdBitLength 或 SeqBitLength,都是可以的,但是慎用 “減小”的操作,因?yàn)檫@可能導(dǎo)致在未來(lái)某天生成的 ID 與過(guò)去老配置時(shí)相同。[允許在系統(tǒng)運(yùn)行之后增加任何一個(gè) BitLength 值]
3.如果必須減小 WorkerIdBitLength 或 SeqBitLength 其中的一項(xiàng),一定要滿(mǎn)足一個(gè)條件:新的兩個(gè) BitLength 之和要大于 老的值之和。[不推薦在運(yùn)行之后縮小任何一個(gè) BitLength 值]
4.上述3條規(guī)則,并未在本算法內(nèi)做邏輯控制,集成方應(yīng)根據(jù)上述規(guī)則做好影響評(píng)估,確認(rèn)無(wú)誤后,再實(shí)施配置變更。
代碼示例
運(yùn)行環(huán)境
1..NET Standard 2.0+
文件說(shuō)明
1.SnowWorkerM1.cs 是雪花漂移算法。
2.SnowWorkerM2.cs 是傳統(tǒng)雪花算法。
雪花漂移算法
var options = new IdGeneratorOptions() { // 設(shè)置WorkerId,默認(rèn)最大2^16-1 WorkerId = 1 }; var newId = new YitIdGenerator(options).NewLong();
傳統(tǒng)雪花算法
var options = new IdGeneratorOptions() { Method = 2, // 默認(rèn)1 WorkerId = 1 }; var newId = new YitIdGenerator(options).NewLong();
options說(shuō)明
options參數(shù)(Method、StartTime除外)只支持漂移算法,不支持傳統(tǒng)雪花算法。
public class IdGeneratorOptions { /// <summary> /// 雪花計(jì)算方法 /// (1|2) /// </summary> public short Method { get; set; } = 1; /// <summary> /// 開(kāi)始時(shí)間(UTC格式) /// 不能超過(guò)當(dāng)前系統(tǒng)時(shí)間 /// </summary> public DateTime StartTime { get; set; } = DateTime.MinValue; /// <summary> /// 機(jī)器碼 /// 與 WorkerIdBitLength 有關(guān)系 /// </summary> public ushort WorkerId { get; set; } = 0; /// <summary> /// 機(jī)器碼位長(zhǎng) /// 范圍:2-21(要求:序列數(shù)位長(zhǎng)+機(jī)器碼位長(zhǎng)不超過(guò)22)。 /// 建議范圍:6-12。 /// </summary> public byte WorkerIdBitLength { get; set; } = 6; /// <summary> /// 序列數(shù)位長(zhǎng) /// 范圍:2-21(要求:序列數(shù)位長(zhǎng)+機(jī)器碼位長(zhǎng)不超過(guò)22)。 /// 建議范圍:6-14。 /// </summary> public byte SeqBitLength { get; set; } = 6; /// <summary> /// 最大序列數(shù)(含) /// (由SeqBitLength計(jì)算的最大值) /// </summary> public int MaxSeqNumber { get; set; } = 0; /// <summary> /// 最小序列數(shù)(含) /// 默認(rèn)11,不小于5,不大于MaxSeqNumber-2 /// </summary> public ushort MinSeqNumber { get; set; } = 11; /// <summary> /// 最大漂移次數(shù)(含), /// 默認(rèn)2000,推薦范圍500-10000(與計(jì)算能力有關(guān)) /// </summary> public int TopOverCostCount { get; set; } = 2000;
生成的ID
默認(rèn)配置:
WorkerId = 6 (最多64個(gè)工作節(jié)點(diǎn)) SeqBitLength = 6
ID示例(基于默認(rèn)配置):
129053495681099 (本算法運(yùn)行1年) 387750301904971 (運(yùn)行3年) 646093214093387 (運(yùn)行5年) 1292658282840139 (運(yùn)行10年) 9007199254740992 (js Number 最大值) 165399880288699493 (普通雪花算法生成的ID)
本算法生成的 ID 值,是 js Number 最大值的 1%-10%,是普通雪花算法值的千分之一,而計(jì)算能力卻超過(guò)普通雪花算法。
技術(shù)支持
開(kāi)源地址:https://gitee.com/yitter/idgenerator
以上就是開(kāi)源一個(gè)c# 新的雪花算法的詳細(xì)內(nèi)容,更多關(guān)于c# 雪花算法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能完整實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能,結(jié)合完整實(shí)例形式分析了C#實(shí)現(xiàn)常見(jiàn)的數(shù)學(xué)運(yùn)算、進(jìn)制轉(zhuǎn)換等相關(guān)操作技巧與界面布局方法,需要的朋友可以參考下2017-08-08C#機(jī)器入門(mén)學(xué)習(xí)之判斷日?qǐng)?bào)是否合格詳解
這篇文章主要給大家介紹了關(guān)于C#機(jī)器入門(mén)學(xué)習(xí)之判斷日?qǐng)?bào)是否合格的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用c#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03C#對(duì)Word文檔的創(chuàng)建、插入表格、設(shè)置樣式等操作實(shí)例
今天小編就為大家分享一篇C#對(duì)Word文檔的創(chuàng)建、插入表格、設(shè)置樣式等操作實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05C#使用System.Net郵件發(fā)送功能踩過(guò)的坑
這篇文章主要介紹了C#使用System.Net郵件發(fā)送功能踩過(guò)的坑,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11C#實(shí)現(xiàn)事件訂閱和解除訂閱的詳細(xì)步驟
在C#中,事件的訂閱和解除訂閱是通過(guò)使用+=和-=操作符來(lái)實(shí)現(xiàn)的,這些操作符分別用于將事件處理程序添加到事件和從事件中移除事件處理程序,本文給大家介紹了C#實(shí)現(xiàn)事件訂閱和解除訂閱的詳細(xì)步驟,需要的朋友可以參考下2024-12-12