天天看點

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

ID是身份辨別,你所涉及的每類業務都會有一個,身份證, 手機号, QQ号。那麼問題來了,如何設計一個算法,能快速生成ID又能有效地避免沖突。

往小了說,在存儲領域每一行資料都會有一個ID,關系型資料庫有 auto increment, 非關系型資料庫,如mongodb有自己的objectID 算法。

對于各種ID我們可以簡化為2類:

1.去中心化,統一長度,規則占坑類, mongodb屬于這一類, guid 屬于這類類。

2.中心化,ID自增,auto increment屬于這一類。

mongodb的ID規則

長度(byte)

含義

4

unix epoch到目前的秒數

3

機器辨別

2

程序辨別

擴充計數

機器辨別可以防止不同機器出現相同ID, 程序辨別則可以在同一台機器上防止出現沖突。

對于這種設計, 我想說 good! 無論是單機還是分布式都可以很有效地解決沖突的問題。

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

即使同一時刻有很多請求,不同機器也不會産生相同的ID,達到了去中心化的ID生成能力。

類似的設計還有twitter snowflake:

長度(bit)

41

unix epoch到目前的毫秒數

10

節點ID

12

sequence

也做到了不同節點去重,不同時間有序,隻是把節點ID的制定交給了使用者。

mysql auto seq

相信大部分研發同學都使用過mysql,auto increment可以有效地解決ID生成。

id會從1開始自增,是以單台Server的情況下是不會有沖突的可能的。

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

這樣的設計一度非常常見于各種前端技術,用過LAMP技術棧的同學應該記得,目前仍被mysql, redis等廣泛使用。

第一種方案是于空間時間相關的,類似于身份證

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

把坑給你空好,生成機制設計好,生成ID就變成了按機制生成數字填坑, 隻要時間不停擺,人口不會短時間内爆增,這個ID就很難重複。

等于把沖突保障交給了系統。

第二種方案與時空無關,隻要生成器還在,就可以一直生産資料,沖突由生成器保障。

以mongodb為例

依賴

unix

epoch到目前的秒數

系統時間

如果因為操作不當,人為把機器的目前時間修改成過去某個時間,其新生成ID的時間部分就有可能沖突。

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

舉例來說,某一年的公曆出現了潤8月(不可能出現),則8月出生的小朋友就要身份證重号了,現終于知道為什麼身份證不使用農曆了吧,喲呵呵。

自增形式的生成器很可能成為瓶頸,争對單點的問題業界已經有一些方案,比如分片自增

有3個節點 p1, p2, p3, 生成的ID規則:

p1: 1,4,7,10,13,16,19,22

p2: 2,5,8,11,14,17,20,23

p3:3,6,9,12,15,18,21,24

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

既使節點A崩潰了,隻要有一個節點還在,系統就能工作。

但是不太好擴充,如果一開始隻配置設定了3台機器,後面系統達到瓶頸了添加機器,就比較麻煩了。

在分布式系統中,ID往往有很多意義,比如散列,如何精确地的把按ID的查詢散列到某台機器上去,是以在一些場景下ID需要包含機器資訊,第一類去中心化ID生成器很好的解決了此類問題。

另外,有時候需要從ID知道系統的資料規模,自增的ID能較好的解決此類問題。

從安全角度上看,不同場景下ID應該有不同的表述,避免被外部猜測。比如微信号在第三方服務中是不能被直接使用的,而是一個64位元組不具備查詢意義的open id。

能不能有一個ID機器既能滿足散列,又能反映資料規模呢,我想是可以的。

本來隻想分享一下現行的生成規則,作為文章的附加,我簡單設計了一個有效的ID生成器。

快速生成,不沖突。

既使系統時間被重置,也不會沖突。

能從最新的ID拿到目前的資料規模。

支援不同場景不同表述。

意義

去中心化

8

統一配置設定全局ID

中心化

設計上将中心化與去中心化結合,對外展示去中心化的ID, 對内展示全部,對統計展示中心化ID。

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計
分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

作為中心化的瓶頸,必須由機器保障其功能可靠。

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

各個節點從全局ID配置設定器批量擷取ID作為預配置設定資源,當節點剩餘預留ID低于門檻值時再次申請。

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計
分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

工作原理也是一樣簡單

單節點崩潰,其他節點仍能崩潰,這個比較簡單。

全局配置設定器的崩潰處理需要在設計上保障,可以同時并存幾個全局生成器,且并不緩存目前最大配置設定ID,該值由資料庫來存儲。

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

全局配置設定的請求是個低頻處理器。

假設工作節點數為N, 系統每秒處理并發為Concurrent, 全局配置設定器的請求頻次F,每次配置設定ID片長度為P, 全局配置設定器個數為M,則有下列公式:

F=Concurrent/(NPM)

假設每秒并發數為100萬 (1秒産生100萬個ID,1秒新增100萬個使用者,實際不可能),有5個工作節點,全局配置設定器個數為4, 每次申請ID片為10000。

F=1000,000 / (5 100004) =5.

100萬每秒的配置設定也隻有每秒幾次的請求,而且P的值可以靈活修改,假設P=100,000(每片10萬個ID),則每秒1個請求都沒有了。

分布式ID生成器的剖析與設計mongodb id引申問題抛出分布式ID的設計

這種情況下對全局配置設定的安全隻需要對資料主從熱備就行了。

理論退化

将上面的規則重新審視一下:

字段

備注

time

machine

process

count

center id

如果隻有前4個,去掉center 隻退化成了mongodb的去中心化ID生成器。

如果去掉前四項,保留center id,則退化成了具備分布式功能的中心化ID生成器。

在一些簡單的業務裡,可以隻需要在這2者中選一個就可以滿足分布式業務的處理。

繼續閱讀