snowflake是twitter開源的分佈式ID生成算法,其核心思想是:一個long型的ID,使用其中41bit作爲毫秒數,10bit作爲機器編號,12bit作爲毫秒內序列號。這個算法單機每秒內理論上最多可以生成1000*(2^12),也就是400W的ID,完全能滿足業務的需求。
借鑑snowflake的思想,結合各公司的業務邏輯和併發量,可以實現自己的分佈式ID生成算法。
舉例,假設某公司ID生成器服務的需求如下:
(1)單機高峯併發量小於1W,預計未來5年單機高峯併發量小於10W
(2)有2個機房,預計未來5年機房數量小於4個
(3)每個機房機器數小於100臺
(4)目前有5個業務線有ID生成需求,預計未來業務線數量小於10個
(5)…
分析過程如下:
(1)高位取從2016年1月1日到現在的毫秒數(假設系統ID生成器服務在這個時間之後上線),假設系統至少運行10年,那至少需要10年*365天*24小時*3600秒*1000毫秒=320*10^9,差不多預留39bit給毫秒數
(2)每秒的單機高峯併發量小於10W,即平均每毫秒的單機高峯併發量小於100,差不多預留7bit給每毫秒內序列號
(3)5年內機房數小於4個,預留2bit給機房標識
(4)每個機房小於100臺機器,預留7bit給每個機房內的服務器標識
(5)業務線小於10個,預留4bit給業務線標識
這樣設計的64bit標識,可以保證:
(1)每個業務線、每個機房、每個機器生成的ID都是不同的
(2)同一個機器,每個毫秒內生成的ID都是不同的
(3)同一個機器,同一個毫秒內,以序列號區區分保證生成的ID是不同的
(4)將毫秒數放在最高位,保證生成的ID是趨勢遞增的
缺點:
(1)由於“沒有一個全局時鐘”,每臺服務器分配的ID是絕對遞增的,但從全局看,生成的ID只是趨勢遞增的(有些服務器的時間早,有些服務器的時間晚)
最後一個容易忽略的問題:
生成的ID,例如message-id/ order-id/ tiezi-id,在數據量大時往往需要分庫分表,這些ID經常作爲取模分庫分表的依據,爲了分庫分表後數據均勻,ID生成往往有“取模隨機性”的需求,所以我們通常把每秒內的序列號放在ID的最末位,保證生成的ID是隨機的。
又如果,我們在跨毫秒時,序列號總是歸0,會使得序列號爲0的ID比較多,導致生成的ID取模後不均勻。解決方法是,序列號不是每次都歸0,而是歸一個0到9的隨機數,這個地方。