SNOWFLAKE
雪花算法是由Twitter公布的分布式主鍵生成算法,它能夠保證不同進程主鍵的不重復性,以及相同進程主鍵的有序性。
在同一個進程中,它首先是通過時間位保證不重復,如果時間相同則是通過序列位保證。 同時由於時間位是單調遞增的,且各個服務器如果大體做了時間同步,那么生成的主鍵在分布式環境可以認為是總體有序的,這就保證了對索引字段的插入的高效性。例如MySQL的Innodb存儲引擎的主鍵。
使用雪花算法生成的主鍵,二進制表示形式包含4部分,從高位到低位分表為:1bit符號位、41bit時間戳位、10bit工作進程位以及12bit序列號位。
- 符號位(1bit)
預留的符號位,恆為零。
- 時間戳位(41bit)
41位的時間戳可以容納的毫秒數是2的41次冪,一年所使用的毫秒數是:365 * 24 * 60 * 60 * 1000
。通過計算可知:
Math.pow(2, 41) / (365 * 24 * 60 * 60 * 1000L);
結果約等於69.73年。ShardingSphere的雪花算法的時間紀元從2016年11月1日零點開始,可以使用到2086年,相信能滿足絕大部分系統的要求。
- 工作進程位(10bit)
該標志在Java進程內是唯一的,如果是分布式應用部署應保證每個工作進程的id是不同的。該值默認為0,可通過屬性設置。
- 序列號位(12bit)
該序列是用來在同一個毫秒內生成不同的ID。如果在這個毫秒內生成的數量超過4096(2的12次冪),那么生成器會等待到下個毫秒繼續生成。
時鍾回撥
服務器時鍾回撥會導致產生重復序列,因此默認分布式主鍵生成器提供了一個最大容忍的時鍾回撥毫秒數。 如果時鍾回撥的時間超過最大容忍的毫秒數閾值,則程序報錯;如果在可容忍的范圍內,默認分布式主鍵生成器會等待時鍾同步到最后一次主鍵生成的時間后再繼續工作。 最大容忍的時鍾回撥毫秒數的默認值為0,可通過屬性設置。
雪花算法主鍵的詳細結構見下圖。
這種方式的優缺點是:
優點:
- 毫秒數在高位,自增序列在低位,整個ID都是趨勢遞增的。
- 不依賴數據庫等第三方系統,以服務的方式部署,穩定性更高,生成ID的性能也是非常高的。
- 可以根據自身業務特性分配bit位,非常靈活。
缺點:
- 強依賴機器時鍾,如果機器上時鍾回撥,會導致發號重復或者服務會處於不可用狀態。