來選擇乙個適合你的分布式ID生成方案吧

2021-10-05 10:35:14 字數 1709 閱讀 5738

在分布式環境中,由於多負載,高併發等原因,很多業務都需要分布式id生成器來生成他們的唯一id,其實方案有很多,今天就結合我們自己使用和了解過的幾種方案來記錄一下。希望多你也有幫助。

uuid是我們很常見的乙個id方案,理論上唯一,生成方式簡單。

但id本身無意義所以不適合做id需要表示含義的內容,如需要像客戶展示的訂單號;而且總長36位過長,去除"-"後也有32位,儲存到db占用儲存空間大。而且作為聚集索引的話,每次去比較轉換新增新的索引時因為b+tree要排序,會有嚴重的效能問題。

uuid適合一些id無意義的場景。如我們在架構中應用到分布式鏈路追蹤的id上。

這種方案其實就是利用mysql的自增主鍵,因為mysql主鍵是聚集索引,物理上連續,並且自增主鍵儲存占用少,效率高;但mysql存在單點問題,不利於資料遷移。而且db會有壓力和瓶頸。我們在一些不太容易變動的如管理員表,選單表中使用自增主鍵。以達到最高的效率。並且沒有分庫分表,遷移等問題。

mysql自增方案有單點問題,所以在mysql集群下使用自增主鍵+步長方案,比如3臺mysql,步長設定3,那麼第乙個mysql中的主鍵就是1 4 7,第二台是2 5 8,第三台是3 6 9。

但step一旦設定好無法擴容。集群無法擴容。我認為該方案實用性一般。目前沒有實踐過。

分布式系統中採用redis做快取很常見。我們也不例外。redis是基於記憶體的一種nosql資料庫,資料操作是單執行緒,利用原子性的incr可以獲取自定義的自增id,比如取用當前時間如2019101010222,再從redis操作incr獲取自增序列拼接。好處就是靈活自定義,id有含義,有趨勢遞增,缺點是占用網路io。效率一般。我們目前使用該方案做銷售、出庫、採購等內部流轉訂單編號。

這個就很知名了。64位2進製數,第一位不用➕41位時間戳➕10位機器碼(或5位機房碼+5位機器碼,可自由定製)➕12位序列(毫秒內計數),理論上毫秒內可生成1024*4096個id,並且趨勢遞增。

但缺點是依賴伺服器時鐘,存在時間回撥問題,如果自己實現該演算法可記錄上一次時間戳,進行比較,短回撥可等待,長回撥只能丟擲異常。我們使用的mybatis plus內建的idworker來做對外訂單號。目前倒是還沒出現什麼問題。

做乙個id表,根據不同業務,設定每個業務的起時值,當前最大值,業務服務每次請求獲取乙個id區間放入自身jvm中。然後更新起始值和最大值,當有id需要使用時,業務服務在jvm內使用執行緒安全方式去獲取id值。這樣就完美解決了每次獲取id到要去查db的效能問題以及步長導致的無法擴容問題,並且就算業務系統掛掉,重新獲取id區間,也不會出現重複問題,當然也可做單獨的id生成服務。

但這個方案問題是如果業務服務負載眾多時,會出現多個服務同時用完當前id區間去請求新的區間,這也可以通過分布式鎖,或者db鎖保證區間的唯一,但是還是會出現請求服務一會快一會慢的情況。

為了解決buffer中忽快忽慢問題,設計使用雙buffer,即在jvm內配置兩個儲存id區間的buffer ,當第一次請求獲取的區間放到buffer1中,當使用達到10%時,另起執行緒請求新的id區間,放入buffer2中.當buffer1中id用盡,自動切換到buffer2,同理,buffer2用到10%時請求新的放入buffer1。但這個方案仍無法解決大面積宕機或者迭代公升級後,服務重啟導致的多例項同時去獲取id區間的併發問題。

記錄了這麼多方案,其實每個方案都有自己的最佳場景。選擇適合自己架構的才是最好的。如果併發沒有一線網際網路公司這麼高,其實沒有必要上雙buffer,只不過是給自己徒增麻煩。如果也根本不遷移,不會涉及到分庫分表,其實自增id更香一些。所以方案可以多了解,但是最重要選擇乙個適合自己業務場景的。

乙個分布式ID的生成器 雪花演算法

coding utf 8 create on 2020 11 23 author sandy import time class snowflake object def init self,datacenterid,machineid self.sequence 0 self.laststmp 1...

常見的分布式唯一ID方案

最近看乙個新系統,發現裡面有很多場景用到唯一id,便蒐羅了一下常見的方案。對於分布式id,需要滿足下面的基本要求 全域性唯一 趨勢遞增 uuid universally unique identifier 全域性唯一識別符號,定義為乙個字串主鍵,採用32位數字組成,編碼採用16進製制,定義了在時間和...

編寫乙個redis分布式鎖

分布式鎖 無論集群伺服器有多少臺,使用了該分布式鎖之後都可以統一的對某乙個資源進行鎖定 某個使用者加鎖之後只有他將分布式鎖釋放了才能讓其它的人操作資源。redis分布式鎖 根據redis中的乙個key的是否存在來實現的 如果key不存在則說明沒有人加鎖,所以建立key成功表示鎖獲取到了 如果key存...