開源一個新的雪花算法(雪花漂移)

IdGenerator

介紹

用一種全新的雪花漂移算法(如下簡稱本算法),讓ID更短、生成速度更快。
核心在於縮短ID長度的同時,還能保持極高併發處理量(50W/0.1s),且具備很強配置能力。前端

需求來源

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

2.你但願這個主鍵是用最少的存儲空間,索引速度更快,Select、Insert 和 Update 更迅速。算法

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

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

5.哪怕 Guid 能自增,但佔用空間大,這也不是你想要的。服務器

6.你但願系統能運行 100 年以上。架構

傳統算法問題

1.生成的ID太長。併發

2.併發量不夠。異步

3.不能解決時間回撥問題。async

4.不支持後補生成前序ID。

5.依賴外部緩存系統。

新算法特色

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

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

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

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

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

6.不依賴任何外部緩存和數據庫。(但 WorkerId 必須由外部指定)

性能數據

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

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

效果

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

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

3.極致性能:500W/1s。

4.全部測試數據均基於8代低壓i7計算。

「我」是什麼

1.本算法是一個類庫,它基於 net standard2.0 基礎庫,不依賴任何第三方組件。

2.本算法不依賴任何外部數據系統(除了要被指定 WorkerId 以外)。

適用範圍

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

2.分佈式項目。

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

如何處理時間回撥

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

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

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

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

能用多久

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

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

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

4.以上全部工做節點,均擁有 50W/0.1s 最大處理速度。

★★集成建議★★

常規集成

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

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

3.異常處理。本算法內部會拋出全部Exception,外部系統 catch 相關信息並作好應對處理,以避免引起更大的系統崩潰。

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

5.訂閱ID異步通知。IIdGenerator.GenIdActionAsync 是一個能夠向外部系統異步發送ID生成消息的事件,它包含的消息類型有"漂移開始、漂移結束、時間回撥",具體參考 Yitter.IdGenTest 的 Program.cs 啓動代碼。不過訂閱ID異步通知會有細微的性能損失。

6.同步或同步調用。你可在外部系統的異步(async標記)方法中調用本算法,同步調用一樣沒問題。

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

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

大型分佈式集成

1.可擴大 WorkerIdBitLength 到最大20,支持 1,048,576 個節點,且不影響上述併發性能(50W/0.1s)。[算法支持]

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

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

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

配置變動

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

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

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

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

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

代碼示例

運行環境

1..NET Standard 2.0+

文件說明

1.SnowWorkerM1.cs 是雪花漂移算法。

2.SnowWorkerM2.cs 是傳統雪花算法。

雪花漂移算法

var options = new IdGeneratorOptions()
{
	// 設置WorkerId,默認最大2^16-1
	WorkerId = 1
};

var newId = new YitIdGenerator(options).NewLong();

傳統雪花算法

var options = new IdGeneratorOptions()
{
	Method = 2,  // 默認1
	WorkerId = 1
};

var newId = new YitIdGenerator(options).NewLong();

options說明

options參數(Method、StartTime除外)只支持漂移算法,不支持傳統雪花算法。

public class IdGeneratorOptions
{
    /// <summary>
    /// 雪花計算方法
    /// (1|2)
    /// </summary>
    public short Method { get; set; } = 1;

    /// <summary>
    /// 開始時間(UTC格式)
    /// 不能超過當前系統時間
    /// </summary>
    public DateTime StartTime { get; set; } = DateTime.MinValue;

    /// <summary>
    /// 機器碼
    /// 與 WorkerIdBitLength 有關係
    /// </summary>
    public ushort WorkerId { get; set; } = 0;

    /// <summary>
    /// 機器碼位長
    /// 範圍:2-21(要求:序列數位長+機器碼位長不超過22)。
    /// 建議範圍:6-12。
    /// </summary>
    public byte WorkerIdBitLength { get; set; } = 6;

    /// <summary>
    /// 序列數位長
    /// 範圍:2-21(要求:序列數位長+機器碼位長不超過22)。
    /// 建議範圍:6-14。
    /// </summary>
    public byte SeqBitLength { get; set; } = 6;

    /// <summary>
    /// 最大序列數(含)
    /// (由SeqBitLength計算的最大值)
    /// </summary>
    public int MaxSeqNumber { get; set; } = 0;

    /// <summary>
    /// 最小序列數(含)
    /// 默認11,不小於5,不大於MaxSeqNumber-2
    /// </summary>
    public ushort MinSeqNumber { get; set; } = 11;

    /// <summary>
    /// 最大漂移次數(含),
    /// 默認2000,推薦範圍500-10000(與計算能力有關)
    /// </summary>
    public int TopOverCostCount { get; set; } = 2000;

生成的ID

默認配置:

WorkerId = 6	(最多64個工做節點)
SeqBitLength = 6

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

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

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

技術支持

開源地址:https://gitee.com/yitter/idgenerator

QQ羣:646049993

即將推出Java、PHP等版本。

相關文章
相關標籤/搜索