分布式系统的唯一ID
2019獨角獸企業重金招聘Python工程師標準>>>
需求
為什么需要唯一ID
讓分布式系統中的需要辨別的元素,都能有唯一的辨識標志。 幾乎所有的業務系統,都有生成一個記錄標識的需求,例如:
為什么需要趨勢有序
記錄標識上的查詢,往往又有分頁或者排序的業務需求,例如:
所以往往要有一個time字段,并且在time字段上建立普通索引(non-cluster index)。
普通索引存儲的是實際記錄的指針,其訪問效率一般會比聚集索引慢,如果記錄標識在生成時能夠基本按照時間有序,則可以省去這個time字段的索引查詢:select message-id (order by message-id) limit 100但是,能這么做的前提是,message-id的生成基本是趨勢時間遞增的。
怎么實現唯一ID
UUID
UUID就是為了要在分布式環境中產生唯一標示符而發布的一個標準。標準中規定UUID長度為16Bytes(128Bits),一般將其表示為550e8400-e29b-41d4-a716-446655440000這種16進制格式,同時將其分為5部分,每部分用-分割,各部分長度分別為8,4,4,12?,F在使用的UUID算法有5個版本,分別使用5種不同的算法計算產生。
優點:
缺點:
mogodb ObjectId
MongoDB中每一條記錄都有一個id字段用來唯一標示本記錄。如果用戶插入數據時沒有顯示提供id字段,那么系統會自動生成一個。ObjectID一共12Bytes,設計的時候充分考慮了分布式環境下使用的情況,所以能保證在一個分布式MongoDB集群中唯一。ObjectID格式如下:
0 4 7 9 12 +--------+------+----+------+ |time |pc |pid |inc | +--------+------+----+------+0~4 Byte是Unix Timestamp。 4~7 Byte是當前機器“hostname/mac地址/虛擬編號”其中之一的MD5結果的前3個字節。 7~9 Byte是當前進程的PID。 9~12Byte是累加計數器或是一個隨機數(只有當不支持累加計數器時才用隨機數)。 最后生成的仍然是一個用16進制表示的串,如47cc67093475061e3d95369d。這里MongoDB的ObjectID相對UUID有個很大的優點就是ObjectID是時間上有序的。另外還有ObjectID本身也包含了很多其它有用的信息,通過直接解碼ObjectID即可直接獲得這些信息。
優點:
缺點:
snowflack
Snowflake是twitter開源的一款獨立的適用于分布式環境的ID生成服務器。生成的ID是64Bits,同時滿足高性能(>10K ids/s),低延遲(<2ms)和高可用。與MongoDB ObjectID類似這里生成的ID也是時間上有序的。編碼方式也和ObjectID類似,如下:
0 41 51 64 +-----------+------+------+ |time |pc |inc | +-----------+------+------+前41bits是以微秒為單位的timestamp。 接著10bits是事先配置好的機器ID。 最后12bits是累加計數器。
有缺點與MongoDB ObjectId類似。但是只要機器ID不重復,應該不會出現重復的ID。
Instagram采用的方式
Instagram要將其中存儲的圖片分片到多個PostgreSQL中,其中生成ID的方案和MongoDB ObjectID類似。整個ID的長度為64Bits,設定為這個長度是為了優化在redis中的存儲。ID的編碼格式如下:
41bits以微秒為單位的timestamp,時間起點從2011-01-01開始。 13bits表示進行邏輯分片的Shard ID。 10bits表示一個累加計數器。 ID的生成邏輯用PL/PGSQL語言寫到PostgreSQL數據庫中,當每次插入數據時由數據庫自動計算生成。 與上面優缺點類似。
Leaf
主要參考:http://wiki.sankuai.com/pages/viewpage.action?pageId=465861190。 利用step設置每個服務能從數據庫拿到的號段大小,能充分的利用id的空間,能保證號段內各個id的時間順序,但是不能保證號段間時間上的順序。
主要優點是id占用字節少(64bits),能充分利用空間,幾乎沒有間隙(按作者說,除非服務器宕機,這種可能會比較小)。
我的想法:
假設應用生命周期為30年(一般極少有應用生命周期30年,linux系統到現在也不超過30年,就算30年到時候也該換方案和架構了),如果時間的精確度是微秒,30年需要通過12位整數保存,使用二進制保存所有12位整數需要大約40位二進制;如果是秒,需要9位整數保存,使用大約30位二進制。假設63位中(除最高位,最高位應該是符號位。)
- 使用微秒方案:前40位給時間,那么還有23位可以給step區間(可表示8百萬個整數,相當于容量為1微秒8百萬個id)。
- 使用秒方案:前30位給時間,那么還有33位可以給step區間(每秒產生id數量與使用微妙方案一秒產生的id數量相同)。
- 使用X秒方案:以此類推
對比秒方案和微秒方案,(X)秒方案可能由于時間對系統能表述的id空間的浪費更少,而且整體能表述的id數量不變,但是遞增趨勢更弱(使用微妙,遞增趨勢更強)。
總結
一般在分布式系統中,與生成唯一ID有關的因素可以來自:
- 時間(基于某一時刻到現在的相對時間,更節約空間)
- 機器邏輯區分ID(如:機器ID,存儲的分片)
- 機器的硬件信息(如:MAC地址等)
- 局部自增
轉載于:https://my.oschina.net/hgfdoing/blog/702986
總結
以上是生活随笔為你收集整理的分布式系统的唯一ID的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu14.04下安装cudnn5
- 下一篇: 门级建模