分散式系統中實現遞增序列該怎麼做呢?

如果是本地的話,直接用 AtomInteger這樣的東西來處理; 那如果是分散式系統中,如何處理比較好呢?


alisql新增引擎支持id持久化遞增


非要實現的話,可以有幾種方式吧:

1. 使用資料庫的主鍵遞增來實現,優點是穩定可靠,缺點是存在單點問題,一旦資料庫出現問題,那個分散式序列服務將不可用。

2. 使用阿里巴巴推出的DRDS服務(分散式關係型資料庫服務_DRDS_詳情介紹),其提供全局唯一數字id服務,幫助您在分散式環境下,繼續保持類似唯一鍵、主鍵等數據的全局(所有節點)唯一性。

3. 使用ZooKeeper ZNode的順序性特點來生成全局序列。


id生成服務啊,可以看看twitter開源的snowflag演算法


固定主機數K的系統中,主機編號為i,以i為初始值,以K為步長自增。缺點,不能動態擴展


我們的方案是使用納秒級別的單向遞增時鐘函數,每秒每cpu 生成干萬級的序列號不在話下,現在我們的KV資料庫的內部版本號就是這個。另外,我們軟體查詢性能比memcache高37%,兼容memcache指令集。與memcached性能對比的測試方法:

1) 運行 memcached, 需要指定8192M內存, 以便可以測試百萬以上的數據量, 指定埠號是1983

memcached -m 8192 -p 1983

我們的程序是動態申請內存, 因此, 不需要指定預先分配的內存量, 直接運行就可以了

haisql_memcache_chinese

我們的軟體默認運行埠是1971

每次測試後需要清理運行環境, memcached直接ctrl_C退出就可以了.

我們的軟體因為退出時默認自動保存內存數據, 因此,需要在退出程序後,執行 rm *.txt;sync;sync 清理掉自動保存的數據, 相當於清空數據,

2)測試軟體 memcslap,

先測試 讀性能 測試軟體自動寫入1萬條記錄, 然後測試讀取900萬次, 我們的軟體執行時間是28.3秒, memcache執行時間是38.8秒, 我們的軟體比memcache快37%

我們的軟體讀性能如下: 讀4.1Kbyte的數據包大小, 4核8線程3.4G主頻DDR3內存, 讀900萬次數據, 900並發, 花費時間28.32秒, 讀性能31.8萬QPS.

第1次是memcached的測試結果, 第2次是我們的軟體測試結果

guo@guo-desktop:~$ memcslap --concurrency=900 --servers=127.0.0.1:1983 --test=get

Threads connecting to servers 900

Took 38.828 seconds to read data

guo@guo-desktop:~$ memcslap --concurrency=900 --servers=127.0.0.1:1971 --test=get

Threads connecting to servers 900

Took 28.320 seconds to read data

測試 寫性能 測試軟體測試寫入100萬條記錄, 我們的軟體執行時間是3.38秒, memcache執行時間是4.078秒, 我們的軟體比memcache快21%

我們的軟體寫性能如下: 寫4.1Kbyte的數據包大小, 4核8線程3.4G主頻DDR3內存, 寫100萬次數據, 100並發, 花費時間3.38秒, 寫性能29.6萬TPS.

第1次是memcached的測試結果, 第2次是我們的軟體測試結果

guo@guo-desktop:~$ memcslap --concurrency=100 --servers=127.0.0.1:1983

Threads connecting to servers 100

Took 4.078 seconds to load data

guo@guo-desktop:~$ memcslap --concurrency=100 --servers=127.0.0.1:1971

Threads connecting to servers 100

Took 3.380 seconds to load data


最方便的,自己搞一個適用於所在公司所有服務的發號器。

對外協議搞成redis或者memcache的,任何語言只要支持socket都能拿號,並且不會重號,代碼本身抄 snowflag 過來就可以。

時間戳+分區ID+自增數 三個欄位每個欄位多少位元組看自己需求定。

如果有專職DBA, alisql 的存儲引擎可以試試,或者每秒發號不超過1000的話,可以用MySQL的自增列。

回答中說ZK的,生產環節ZK作為發號器性能很值得商量的,分散式服務沒必要往發號器上使,性能非常受限制的。

或者可以搞redis。


ETCD 的 CAS 機制


剛好我們項目也有用這個,自己實現了一個全局id生成器,單獨節點,起了一個單線程服務生成,服務會預分配,每次分配完會同時寫資料庫。外部使用時,每次其實都是走的內存生成,速度還是很快的。如果伺服器宕機,雖然再起個進程從資料庫讀,中間可能會浪費幾個預分配的id,不過這個其實也可以定期刷,基本不浪費的。當然再好點,可能需要做個主備自動切換的更好。

現成的方案就是前面有人說的用資料庫或者zookeeper,不過感覺zookeeper相對複雜點


推薦閱讀:

分散式系統理論進階 - Paxos變種和優化
XGBoost, LightGBM性能大對比
分散式資源管理
[NIPS2012] 針對深度學習的大型分散式訓練
[DNN] 嘗試理解深度神經網路的Large-batch魔咒

TAG:分散式系統 | ZooKeeper |