SnowFlake 雪花算法
SnowFlake算法生成的ID大致上是按照時間遞增的,用在分佈式系統中時,需要注意數據中心標識和機器標識必須唯一,這樣就能保證每個節點生成的ID都是唯一的。它可以滿足Twitter每秒上萬條消息ID分配的請求,這些消息ID是唯一的且有大致的遞增順序,且是一個64位整形,即8字節,可以展示為一個Long類型的整數。結構如下(每一部分用“-”符號分隔):
- 1位標識部分,在java中由於long的最高位是符號位,正數是0,負數是1,一般生成的ID為正數,所以為0;
- 41位時間戳部分,這個是毫秒級的時間,一般實現上不會存儲當前的時間戳,而是時間戳的差值(當前時間-固定的開始時間),這樣可以使產生的ID從更小值開始;41位的時間戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年;
- 10位節點部分,Twitter實現中使用前5位作為數據中心標識(Data Center ID),後5位作為機器標識(Worker ID),可以部署1024個節點;
- 12位序列號部分,支持同一毫秒內同一個節點可以生成4096個ID;
Snowflake算法核心
把時間戳,工作機器id,序列號組合在一起。
SnowFlake 的優點如下:
- 比UUID 短,一般為9-17位。
- 生成的ID是數字,可以做到單調遞增。由於無法統一分佈式環境中每臺服務器的時鐘,它只能做到單臺機器單調遞增,無法做到全局遞增。
- 性能非常出色,吞吐量達到幾十萬TPS。
應用場景
參考上面的SnowFlake的優點,對應的應用場景如下。
1、數據庫表主鍵:很多DBA在大型生產應用禁用auto_increment的ID,這時可以選SnowFlake替代。
2、TraceId:分佈式系統追蹤,希望用一個ID貫穿所有子系統來追蹤分佈式交互過程。如果系統產生一個Exception,我們需要對Exception編號等。
3、短時間內訪問特別大,需要生成大量的唯一ID。
SnowFlake算法,Java版源代碼
Github 源碼地址:
https://github.com/rickiechina/CloudNative/blob/master/common/src/main/java/com/cloudnative/common/SnowflakeIdWorker.java
在具體的業務場景中,可以將上述代碼進一步封裝。
如想基於不同的table name,或者業務創建,實例化不同SnowflakeIdWorker 對象,然後存放在HashMap,在調用時,取出對應SnowflakeIdWorker對象,調用nextId() 方法。
Twitter 官方code:
https://github.com/twitter-archive/snowflake
閱讀更多 軟件架構 的文章