雲栖号資訊:【 點選檢視更多行業資訊】
在這裡您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!
背景
在分布式場景中,很多地方需要生成全局唯一的id,如資料庫分庫分表後需要用唯一id代替單機版本的自增id。發号器的基本要求是
- 全局唯一,無論如何都不能重複
某些場景下還要求單調遞增,如排序需求等。
網上有很多介紹發号器的文章,比如美團的《Leaf——美團點評分布式ID生成系統》,有贊的《如何做一個靠譜的發号器》等。本文聚焦高可用,高性能
- 高可用:不會因為系統故障導緻服務不可用或發号重複
- 高性能:發号器通常是一個非常高并發的系統,性能足夠的同時也可以水準擴容
在基本的要求下,常見的解決方案有哪些?他們是否是高可用,高性能的呢?
snowflake方案
snowflake 采用41位時間戳加10位機器id加12位序列号的方式生成,序列号在單一程序内可使用AtomicLong來生成,10位機器号可支援1024台機器
該算法優點是:
- 算法簡單,易于實作,不依賴任何第三方系統,性能非常高;
- 叢集無狀态,可随意擴縮容,可認為是高可用系統。
缺點是:
- 高10位的時間戳和低位自增序列号可保證單調增,但機器号無法保證,如機器号為2在某一時刻先生成id,機器号為1在同一時刻後生成id,則不能保證單調性;
- 依賴時間戳,如果時鐘回撥,可能會生成重複的id。綜合來看,snowflake方案符合基本要求,性能非常高,但其存在時鐘回撥問題,因而是高性能但不是高可用的方案。
基于資料庫方案
利用資料庫的自增id特性實作,該方案優點:
- 實作比較簡單,隻依賴資料庫;
- 沒有時鐘回撥問題;
- 生成的id單調遞增。
缺點:
- 性能被資料庫限制,資料庫的單機寫入性能有限,也無法擴縮容;
- 資料庫存在單點故障,如果是主從架構,取決于是異步複制、半同步複制、全同步複制配置,隻有全同步複制才能保證可用性,其他配置無法保證主從資料的一緻性,一旦主庫發生故障,主庫的變更還未應用到從庫,則主從切換後可能會存在發号重複的問題。
同理,這裡的資料庫也可以替換為redis,利用redis的incr來實作,但redis隻有異步複制,更加無法保證資料一緻性。
綜合來看,基于資料庫的方案如果不開啟全同步複制,就不是高可用方案,如果開啟全同步複制,則性能一定會有問題(就算不開啟全同步複制也會有性能問題)。
基于資料庫的号段方案
本方案是對資料庫方案的一種性能優化,每次從資料庫取回的不是一個id,而是一個号段,在單獨程序内通過鎖保證每次發放一個唯一的id,甚至可以在系統快要發放完号碼時異步地去擷取下一個号段,該方案性能明顯高于資料庫方案,但也失去了id單調遞增的特性,如果開啟全同步複制,則可認為是一個高可用的方案,通過調大号段的長度,可以達到高性能的要求。
基于多主庫的資料庫方案
本方案也是對資料庫号方案的一種優化,采用多台資料庫,假設3台主庫設定自增id起始分别為1,2,3,步長都設定為3,這樣1号資料庫擷取的自增id為1,4,7...,2号資料庫擷取的自增id為2,5,8...,3号資料庫擷取的自增id為3,6,9...,他們永遠不會重複。系統每次取号段時采取輪詢政策,如果有一台資料庫擷取失敗,則繼續從下一個資料庫擷取。該方案解決了資料庫的高可用問題,個别資料庫當機不影響系統正常運作。高性能也是通過号段的方式來解決,如果運作過程中對資料庫進行水準擴容則比較困難。
基于一緻性協定的方案
上面資料庫的高可用問題主要來源于主從資料不一緻,如果使用一緻性協定來保證資料的一緻性,就可以解決高可用問題,目前最常使用的raft算法,可以保證資料複制到半數以上機器。在我們每擷取一個号段後,已發出的号段都被持久化到半數以上機器,并且最終複制到所有機器,當master挂掉後raft重新選舉。有贊的《如何做一個靠譜的發号器》就是采取這種辦法,他們使用的元件是etcd。甚至可以基于開源的raft庫來自己實作一個發号器,如果要自己來實作一個靠譜的raft協定,還是比較困難的,開源的raft庫可選用螞蟻開源的SOFAJRaft。
總結
- 發号器的高性能主要依靠号段的方式來解決;
- 發号器的高可用可以依靠資料庫的高可用、多主庫、一緻性協定來實作。
【雲栖号線上課堂】每天都有産品技術專家分享!
課程位址:
https://yqh.aliyun.com/live立即加入社群,與專家面對面,及時了解課程最新動态!
【雲栖号線上課堂 社群】
https://c.tb.cn/F3.Z8gvnK
原文釋出時間:2020-05-19
本文作者:捉蟲大師
本文來自:“
掘金”,了解相關資訊可以關注“掘金”