雪花算法Snowflake
雪花Id生成算法,是鼎鼎有名的分布式Id生成算法。它的優點在于,在分布式系統中快速生成有時間順序的唯一編號!Snowflake實測每秒可生成900萬個唯一Id。
Nuget包:NewLife.Core
源碼地址:
https://github.com/NewLifeX/X/blob/master/NewLife.Core/Data/Snowflake.cs
核心原理
使用一個 64 bit 的 long 型的數字作為全局唯一 id。在分布式系統中的應用十分廣泛,且ID 引入了時間戳,基本上保持自增。
格式:1bit保留 + 41bit時間戳 + 10bit機器 + 12bit序列號
第一位不使用,主要是為了避免部分場景變成負數;
41位時間戳,也就是2的41次方,毫秒為單位,足夠保存69年。這里一般存儲1970年以來的毫秒數,建議各個系統根據需要自定義這個開始日期;
10位機器碼,理論上可以表示1024臺機器,也可以拆分幾位表示機房幾位表示機器。這里默認采用本機IPv4地址最后兩段以及進程Id一起作為機器碼,確保機房內部不同機器,以及相同機器上的不同進程,擁有不同的機器碼;
12位序列號,表示范圍0~4095,一直遞增,即使毫秒數加一,這里也不會歸零,避免被惡意用戶輕易猜測得到前后訂單號;
生成Id
NewId用于生成新的唯一Id
/// <summary>獲取下一個Id</summary> /// <returns></returns> public virtual Int64 NewId();/// <summary>獲取指定時間的Id,帶上節點和序列號。可用于根據業務時間構造插入Id</summary> /// <param name="time">時間</param> /// <returns></returns> public virtual Int64 NewId(DateTime time);無參版默認使用當前時間生成唯一Id,也可以給指定時間生成唯一Id。
以下是采用雪花Id作為訂單號。
解析Id
大型數據表,例如訂單表、日志表等,可以使用Int64作為主鍵,然后使用雪花Id。因為雪花Id內帶有時間戳信息,因此我們可以根據主鍵Id來直接搜索指定時間區間的數據。
/// <summary>時間轉為Id,不帶節點和序列號。可用于構建時間片段查詢</summary> /// <param name="time">時間</param> /// <returns></returns> public virtual Int64 GetId(DateTime time);GetId用于計算指定時間的基準Id,只有最高的時間部分,機器碼和序列化為零。我們在計算指定時間區間(start, end)內的數據時,可以有:
Select * from Order where Id>=Get(start) and Id<GetId(end);拿到一個雪花Id,也可以從中解析得到時間等信息
/// <summary>嘗試分析</summary> /// <param name="id"></param> /// <param name="time">時間</param> /// <param name="workerId">節點</param> /// <param name="sequence">序列號</param> /// <returns></returns> public virtual Boolean TryParse(Int64 id, out DateTime time, out Int32 workerId, out Int32 sequence);解析訂單號 152075078181383514 ,時間基準設為 2020年1月1日
總結
在分布式系統中,雪花Id具有非常重要的意義。星塵大量使用雪花Id,用于存儲跟蹤數據和采樣數據,以前必須先插入跟蹤數據得到自增Id然后才能插入采樣數據(需要關聯)的問題迎難而解,兩者都可以同時走批量插入。
對于日志型數據表,強烈推薦使用雪花Id,因為它帶有時間戳信息,等同于省去了CreateTime字段的索引。
總結
以上是生活随笔為你收集整理的雪花算法Snowflake的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用 Tye 辅助开发 k8s 应用竟如
- 下一篇: Delphi 26 岁