生成的ID是64Bits整型數,同時滿足高性能(>10K ids/s),低延遲(<2ms)和高可用。
在分布式系統中,需要生成全局UID的場合還是比較多的,twitter的snowflake解決了這種需求,實現也還是很簡單的,除去配置信息,核心代碼就是毫秒級時間41位+機器ID 10位+毫秒內序列12位。
該項目地址為:https://github.com/twitter/snowflake是用Scala實現的。
python版詳見開源項目https://github.com/erans/pysnowflake。
核心代碼為其IdWorker這個類實現,其原理結構如下,我分別用一個0表示一位,用—分割開部分的作用:
0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---0000000000 00
在上面的字符串中,第一位為未使用(實際上也可作為long的符號位),接下來的41位為毫秒級時間,然后5位datacenter標識位,5位機器ID(并不算標識符,實際是為線程標識),然后12位該毫秒內的當前毫秒內的計數,加起來剛好64位,為一個Long型。
這樣的好處是,整體上按照時間自增排序,并且整個分布式系統內不會產生ID碰撞(由datacenter和機器ID作區分),并且效率較高,經測試,snowflake每秒能夠產生26萬ID左右,完全滿足需要。
1. 41位的時間序列(精確到毫秒,41位的長度可以使用69年)
2. 10位的機器標識(10位的長度最多支持部署1024個節點,支持多機房的分布式,需要使用zookeeper)
3. 12位的計數順序號(12位的計數順序號支持每個節點每毫秒產生4096個ID序號) 最高位是符號位,始終為0。
//64--------63-----------22-----------12----------0
//符號位 |41位時間 |10位機器碼 |12位自增碼|
對twitter而言這樣的ID生成方案滿足:
1.每秒能夠生成足夠的ID數。 2.生成的ID按照時間大致有序。
用zookeeper的原因是需要獲取一個workerId,當然你也可以給分布式節點手工指定不同的workderId,那樣就不需要用zookeeper了。
除了最高位bit標記為不可用以外,其余三組bit占位均可浮動,看具體的業務需求而定。默認情況下41bit的時間戳可以支持該算法使用到2082年,10bit的工作機器id可以支持1023臺機器,序列號支持1毫秒產生4095個自增序列id。