分散式主鍵生成

selrain_公眾號也叫selrain發表於2018-08-20

分散式主鍵生成

背景:

網際網路行業裡面,新開一個專案基本上都是需要分庫分表的,再差也要先分個表;那麼id就需要全域性唯一,下面介紹幾種ID生成方案。


常見方法介紹:

snowflake(雪花演算法):

Long型 64Bit位:1bit保留+41bit時間戳+10bit程式id+12bit序列號。 41-bit的時間可以表示(1L<<41)/(1000L360024*365)=69年的時間,10-bit機器可以分別表示1024臺機器。如果我們對IDC劃分有需求,還可以將10-bit分5-bit給IDC,分5-bit給工作機器。這樣就可以表示32個IDC,每個IDC下可以有32臺機器,可以根據自身需求定義。12個自增序列號可以表示2^12個ID,理論上snowflake方案的QPS約為409.6w/s,這種分配方式可以保證在任何一個IDC的任何一臺機器在任意毫秒內生成的ID都是不同的。

分散式主鍵生成

優點:

  • 毫秒數在高位,自增序列在低位,整個ID都是趨勢遞增的
  • 不依賴資料庫等第三方系統,以服務的方式部署,穩定性更高,生成ID的效能也是非常高的
  • 可以根據自身業務特性分配bit位,非常靈活

缺點:

  • 強依賴機器時鐘,如果機器上時鐘回撥,會導致發號重複或者服務會處於不可用狀態

實現:

sharding-jdbc內建了雪花演算法的實現,個人覺得還不錯,可以翻翻看裡面的程式碼

資料庫生成:

通過設定不同的業務(biz_tag),每次獲取一個segment(step決定大小)號段的值。用完之後再去資料庫獲取新的號段

biz_tag step maxId
activity 1000 1000

重要欄位說明:biz_tag用來區分業務,max_id表示該biz_tag目前所被分配的ID號段的最大值,step表示每次分配的號段長度。 優點:

  • ID號碼是趨勢遞增的8byte的64位數字,滿足資料庫儲存的主鍵要求
  • 容災性高:有號碼快取,即使db當機了,短時間內仍然可以提供附服務
  • 可以自定義max_id的大小,非常方便業務從原有的ID方式上遷移過來

缺點:

  • TP999資料波動大,當號段使用完之後還是會hang在更新資料庫的I/O上,tg999資料會出現偶爾的尖刺
  • ID號碼不夠隨機,能夠洩露發號數量的資訊,不太安全
  • DB當機會造成整個系統不可用 #####雙buffer優化: 對於第一個缺點:主要是記憶體中的號碼段用完了再去DB取,這時候會出現短暫的堵塞。如果請求DB的網路和DB的效能穩定,這種情況對系統的影響是不大的,但是假如取DB的時候網路發生抖動,或者DB發生慢查詢就會導致整個系統的響應時間變慢 為此,我們希望DB取號段的過程能夠做到無阻塞,不需要在DB取號段的時候阻塞請求執行緒,即當號段消費到某個點時就非同步的把下一個號段載入到記憶體中。而不需要等到號段用盡的時候才去更新號段。這樣做就可以很大程度上的降低系統的TP999指標。詳細實現如下圖所示:

分散式主鍵生成

採用雙buffer的方式,服務內部有兩個號段快取區segment。當前號段已下發10%時,如果下一個號段未更新,則另啟一個更新執行緒去更新下一個號段。當前號段全部下發完後,如果下個號段準備好了則切換到下個號段為當前segment接著下發,迴圈往復。


最後,歡迎follow我的個人訂閱號:

分散式主鍵生成

相關文章