1.發號器介紹
什么是發號器?
全局唯一ID生成器,主要用於分庫分表唯一ID,分布式系統數據的唯一標識。
是否需要發號器?
1)是否需要全局唯一。
分布式系統應該不受單點遞增ID限制,中心式的會涉及到鎖的問題,而鎖意味着成本和性能的下降。
2)時間相關。
時間是天然唯一遞增的,不過每秒或每毫秒生成一個唯一ID明顯不夠,這時候就需要引入SequenceID,使得發號器能在秒或毫秒時間內繼續遞增,如果引入服務器實例編號、業務編號,多維依賴能使ID值在同一秒或毫秒內生成的更多。
如果要做到精確有序,需要對SequenceID進行並發控制,性能上肯定會打折。所以在秒或毫秒級別上不再保證順序是系統應該要考慮是否能接受的地方。
3)可反解,解開的是什么?
ID反解能得到這條信息是什么時候生成的,由什么業務生成的,在哪台服務器上生成,這相當於身份證,身份證就是一個典型的分布式ID生成器。比如:
4)可制造(偽造一個過去的一條業務記錄)。
比如在存儲失敗時,可能需要臨時導出請求供后續處理,而后續處理時已經離開了當時的時間點,順序跟其他系統錯開了。我們需要制造出這樣的ID 以便系統好像一直正常運行一樣,可制造的 ID讓你可以控制生產日期。為什么不用UUID?字符串型查詢效率低;無序;太長了...
2.業界已知的ID設計
1)SnowFlake
推特的分布式自增ID算法。41bit留給毫秒時間,10bit給MachineID,也就是機器要預先配置,剩下12位留給Sequence。
這里的時間戳保存的是當前時間與固定過去時間得一個差值,不是當前時間。這樣的好處是能使用更長時間,而且不受年份限制,只取決於從什么時候開始用的,2^41 / 1000360024*365=69年。
如果保存的是當前時間戳,最多只能使用到2039
年。2^41=2199023255552=2039/9/7 23:47:35
理論上單機速度:2^12*1000 = 4 096 000/s
2)微博
微博使用了秒級的時間,用了30bit,Sequence 用了15位,理論上可以搞定2^15=3.2w/s的速度。
用4bit來區分IDC,也就是可以支持16個 IDC。剩下的有2bit 用來區分業務,由於當前發號服務是機房中心式的,1bit 來區分熱備。30+15+4+2+1=52
服務端使用memcache協議。
3.設計細節
2+41+4+10+7 = 64
- 固定位01, 0表示符號位,1統一長度19位
- 4位服務器編號可支持開啟16個集群實例
- 10位業務編號支持1024個業務分類
- 理論上單機速度2^7*1000 = 128 000/s
運行流程圖
為什么要用到swoole?
-
1)使用Redis傳輸協議,作為內部數據交互比http更高效。
-
2)swoole_table共享內存變量,解決多進程間的數據共享和同步問題。
-
3)swoole_atomic多進程間的數據同步加鎖。