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,達到了去中心化的ID生成能力。
類似的設計還有twitter snowflake:
長度(bit)
41
unix epoch到目前的毫秒數
10
節點ID
12
sequence
也做到了不同節點去重,不同時間有序,隻是把節點ID的制定交給了使用者。
mysql auto seq
相信大部分研發同學都使用過mysql,auto increment可以有效地解決ID生成。
id會從1開始自增,是以單台Server的情況下是不會有沖突的可能的。
這樣的設計一度非常常見于各種前端技術,用過LAMP技術棧的同學應該記得,目前仍被mysql, redis等廣泛使用。
第一種方案是于空間時間相關的,類似于身份證
把坑給你空好,生成機制設計好,生成ID就變成了按機制生成數字填坑, 隻要時間不停擺,人口不會短時間内爆增,這個ID就很難重複。
等于把沖突保障交給了系統。
第二種方案與時空無關,隻要生成器還在,就可以一直生産資料,沖突由生成器保障。
以mongodb為例
依賴
unix
epoch到目前的秒數
系統時間
如果因為操作不當,人為把機器的目前時間修改成過去某個時間,其新生成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
既使節點A崩潰了,隻要有一個節點還在,系統就能工作。
但是不太好擴充,如果一開始隻配置設定了3台機器,後面系統達到瓶頸了添加機器,就比較麻煩了。
在分布式系統中,ID往往有很多意義,比如散列,如何精确地的把按ID的查詢散列到某台機器上去,是以在一些場景下ID需要包含機器資訊,第一類去中心化ID生成器很好的解決了此類問題。
另外,有時候需要從ID知道系統的資料規模,自增的ID能較好的解決此類問題。
從安全角度上看,不同場景下ID應該有不同的表述,避免被外部猜測。比如微信号在第三方服務中是不能被直接使用的,而是一個64位元組不具備查詢意義的open id。
能不能有一個ID機器既能滿足散列,又能反映資料規模呢,我想是可以的。
本來隻想分享一下現行的生成規則,作為文章的附加,我簡單設計了一個有效的ID生成器。
快速生成,不沖突。
既使系統時間被重置,也不會沖突。
能從最新的ID拿到目前的資料規模。
支援不同場景不同表述。
意義
去中心化
8
統一配置設定全局ID
中心化
設計上将中心化與去中心化結合,對外展示去中心化的ID, 對内展示全部,對統計展示中心化ID。
作為中心化的瓶頸,必須由機器保障其功能可靠。
各個節點從全局ID配置設定器批量擷取ID作為預配置設定資源,當節點剩餘預留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個請求都沒有了。
這種情況下對全局配置設定的安全隻需要對資料主從熱備就行了。
理論退化
将上面的規則重新審視一下:
字段
備注
time
machine
process
count
center id
如果隻有前4個,去掉center 隻退化成了mongodb的去中心化ID生成器。
如果去掉前四項,保留center id,則退化成了具備分布式功能的中心化ID生成器。
在一些簡單的業務裡,可以隻需要在這2者中選一個就可以滿足分布式業務的處理。