在那裡產生,和消費端進行判斷等和這個id沒有關係,這個id的要求就是局部唯一或者全局唯一即可,由於這個id是唯一的,可以用來當資料庫的主鍵,既然要做主鍵那麼之前剛剛好發過一篇文章:從開發者角度談Mysql(1):主鍵問題,文章重點提到為什麼需要自增、或者趨勢自增的好處。(和Mysql數據存儲做法有關)。
快(哈哈,天下武功唯快不破)。
沒有啥依賴,實現也特別簡單。
知道原理之後可以根據實際情況調整各各位段,方便靈活。
只能趨勢遞增。(有些也不叫缺點,網上有些如果絕對遞增,競爭對手中午下單,第二天在下單即可大概判斷該公司的訂單量,危險!!!)
依賴機器時間,如果發生回撥會導致可能生成id重複。
下面重點討論時間回撥問題。
snowflake演算法時間回撥問題思考
由於存在時間回撥問題,但是他又是那麼快和簡單,我們思考下是否可以解決呢? 零度在網上找了一圈沒有發現具體的解決方案,但是找到了一篇美團不錯的文章:Leaf——美團點評分散式ID生成系統(https://tech.meituan.com/MT_Leaf.html)文章很不錯,可惜並沒有提到時間回撥如何具體解決。下面看看零度的一些思考:
分析時間回撥產生原因
第一:人為操作,在真實環境一般不會有那個傻逼幹這種事情,所以基本可以排除。
第二:由於有些業務等需要,機器需要同步時間伺服器(在這個過程中可能會存在時間回撥,查了下我們伺服器一般在10ms以內(2小時同步一次))。
解決方法
由於是分布在各各機器自己上面,如果要幾台集中的機器(並且不做時間同步),那麼就基本上就不存在回撥可能性了(曲線救國也是救國,哈哈),但是也的確帶來了新問題,各各結點需要訪問集中機器,要保證性能,百度的uid-generator產生就是基於這種情況做的(每次取一批回來,很好的思想,性能也非常不錯)https://github.com/baidu/uid-generator。
如果到這裡你採納了,基本就沒有啥問題了,你就不需要看了,如果你還想看看零度自己的思考可以繼續往下看看(零度的思考只是一種思考 可能也不一定好,期待你的交流。),uid-generator我還沒有細看,但是看測試報告非常不錯,後面有空的確要好好看看。
下面談談零度自己的思考,之前也大概和美團Leaf作者交流了下,的確零度的這個可以解決一部分問題,但是引入了一些其他問題和依賴。是零度的思考,期待更多的大佬給點建議。
時間問題回撥的解決方法:
當回撥時間小於15ms,就等時間追上來之後繼續生成。
當回撥時間大於15ms時間我們通過更換workid來產生之前都沒有產生過的來解決回撥問題。
首先把workid的位數進行了調整(15位可以達到3萬多了,一般夠用了)
Snowflake演算法稍微調整下位段:
sign(1bit)
固定1bit符號標識,即生成的暢途分散式唯一id為正數。
delta seconds (38 bits)
當前時間,相對於時間基點"2017-12-21"的增量值,單位:毫秒,最多可支持約8.716年
worker id (15 bits)
機器id,最多可支持約3.28萬個節點。
sequence (10 bits)
每秒下的並發序列,10 bits,這個演算法單機每秒內理論上最多可以生成1000*(2^10),也就是100W的ID,完全能滿足業務的需求。
由於服務無狀態化關係,所以一般workid也並不配置在具體配置文件裡面,看看我這篇的思考,為什麼需要無狀態化。高可用的一些思考和理解,這裡我們選擇redis來進行中央存儲(zk、db)都是一樣的,只要是集中式的就可以。
下面到了關鍵了:
現在我把3萬多個workid放到一個隊列中(基於redis),由於需要一個集中的地方來管理workId,每當節點啟動時候,(先在本地某個地方看看是否有 借鑒弱依賴zk 本地先保存),如果有那麼值就作為workid,如果不存在,就在隊列中取一個當workid來使用(隊列取走了就沒了 ),當發現時間回撥太多的時候,我們就再去隊列取一個來當新的workid使用,把剛剛那個使用回撥的情況的workid存到隊列裡面(隊列我們每次都是從頭取,從尾部進行插入,這樣避免剛剛a機器使用又被b機器獲取的可能性)。
有幾個問題值得思考:
如果引入了redis為啥不用redis下發id?(查看分散式系統唯一ID生成方案匯總會獲得答案,我們這裡僅僅是用來一致性隊列的,能做一致性隊列的基本都可以)。
引入redis就意味著引入其他第三方的架構,做基礎框架最好是不要引用(越簡單越好,目前還在學習提高)。
redis一致性怎麼保證?(redis掛了怎麼辦,怎麼同步,的確值得商榷。可能會引入會引入很多新的小問題)。
總結
所以選擇類似百度的那種做法比較好,集中之後批取,零度的思考雖然思考了,但是從基礎組件來看並不是特別合適,但是也算一種思路吧。期待與大佬們的交流。