2016-06-17 baidu 架構師之旅
id分配是社群類產品的提交環節中必不可少的一步。任何ugc類內容產生時往往需要分配乙個對應的id。
id分配的幾種方式
方式一:單點自增分配。全域性由乙個模組來負責生成id,可保證id從0開始連續遞增,資料一般放在本地檔案。簡潔,但致命的問題是單點故障會導致服務整體不可用。
方式一改進:為該模組提供主從複製的能力,或者乾脆將資料放在mysql裡,利用mysql的主從複製,都一定程度上增強了可用性,減輕了單點故障的影響。
方式二:隨機/雜湊分配。通過一些hash演算法,比如以時間+隨機串為key的md5生成乙個唯一的id,關鍵點在於演算法和key的選擇要避免衝突。
最典型的就是uuid,uuid的標準型式包含32個16進製數字,以連字型大小分為五段,形式為8-4-4-4-12的32個字元,如550e8400-e29b-41d4-a716-446655440000。libuuid提供了以時間或者隨機數為基的uuid。uuid的最大缺點是位數太長,128位,在絕大多數應用和語言裡對128位整數的支援都不好。
方式二改進:有條件的進行壓縮。twitter的snowflake使用 time – 41 bits + configured machine id – 10 bits + sequence number – 12 bits的形式分配id,共63位,最高部分使用毫秒級的時間戳,保證了一定程度的有序性,機器標示使用10位,最多可容納1024個分配器,最後的12位序列號可以支援在1ms內產生4096個不重複的id。從工程角度,這些都足夠用了。但對系統時間的依賴性非常強,需要關閉ntp的時間同步功能,或者當檢測到ntp時間調整後,拒絕分配id。
我們的需求和多idc的挑戰
我們的實際情況是:
· 一些老模組依賴於從0開始自增的id,資料在記憶體或者檔案中以id為偏移來儲存的。
· 一些系統依賴於id的增長做資料分片,例如按取除後分表,因此要求id在整體上是比較均衡的增長。
· 在多idc環境,高延遲加不穩定的網路環境,要求各個分配器彼此之間無需協作,或者可以容忍短期內不可協作。
· 對於一些古董級的老系統來說,還在使用32位的id,63位id還是太大了。
因此,我們需要一種分布式高可用、從0開始自增、基本均衡、能夠相容老系統的id分配方案。
取模或分段的分布式分配
基於方案一再改進一步,將整個id空間按取模或分段等分為若干個獨立的id子空間,每個id子空間由乙個獨立的分配器負責。
優點:簡單,各個id分配器無需協作,即使發生網路劃分時,也可保證可用性和id的不衝突。
如果在國際化環境的多idc裡進行部署,需要預先將id空間劃分為n份,每個國家裡部署若干份。每個idc內應用只連本idc的id分配服務。
在均衡性上的不足:在同乙個idc內,均衡性可以在接入層均衡演算法保證,但是在多個idc裡,id分配器個數的比例和id增長的服務往往是不吻合的,因此在多個idc內,id是無法保證均衡增長的。
均衡性上的改進
將id分配分為兩層:
· 上層的「id分配器」對應用暴露,提供一次申請乙個id的介面,一般本idc的應用只連本idc的id分配器。
·下層的「段分配器」對「id分配器」提供服務。id分配器「知曉」所有idc的所有段分配器的存在,使用均衡策略向段分配器申請乙個id段,當所持有的id段快耗盡時,再請求下乙個段。
唯一性:全域性中,根據分片規則,每個段分配器會持有不同的id段。例如下表中,每個段的大小是100,段分配器a持有分片0和分片1。對於每個分片而言,是乙個個跳躍的id段。特殊的,當段大小為1時,段分配器就是改進前的id分配器。
均衡策略:均衡策略在id分配器來實現,簡單的講,是乙個輪詢策略。每個id分配器會輪詢下游段分配器的狀態,並選中id段的最小的那個,然後發起id段申請。由於不會加鎖,當多個id分配器同時競爭時,可能會出現獲取的id段不是全域性最小的,可以附加一些策略來調優,比如再多獲取一次,並本地排序。從整體上而言,id還是比較均衡的,可滿足需求。
可用性:當發生網路劃分時,本idc的id分配器可以只連線本idc的段分配器,成功的申請到id段。整個系統可容忍一定時間內不可協作,長時間不可協作的唯一危害是id增長不均衡,此時,就退化為改進前的方案。
多idc環境的適應性:id分配器需要和所有idc的段分配器互動,但是互動頻率很低,同時和提供id分配服務是兩個獨立的階段,不會受到多idc網路環境的干擾。
效果改進後的id分配方案成功的滿足了系統重構過程中的相容需求,並且部署在全球多個idc內為系統提供全域性唯一的id分配服務。
關於分布式環境下的id生成
1 public class idworker2 maxworkerid 4445 if datacenterid maxdatacenterid datacenterid 0 46 throw new argumentexception string.format datacenterid id ...
分布式環境下的id生成方法
前幾天研究資料庫分表分庫的問題,其中有乙個關鍵的地方就是生成唯一鍵的問題,假如資料表有1億條資料,而且還在不斷的增加,這裡我們就需要考慮到分表分庫,假設我們採用hash或者是使用者取模求餘的方法將這個表拆分成10個表,每個表的結構相同,其中有乙個主鍵id,那麼10個表中的id需要唯一不同,在單錶的時...
甜甜的分布式ID
生活太苦了,只能把技術變甜了。id是資料的唯一標識,傳統的做法是利用 uuid 和資料庫的自增 id,在網際網路企業中,大部分公司使用的都是 mysql,並且因為需要支援事務,所以通常會使用 innodb 儲存引擎,uuid太長以及無序,所以並不適合在 innodb 中來作為主鍵,自增 id 比較合...