今天介紹的雪花算法:Snowflake,可以讓負責生成分布式 ID 的每臺機器在每毫秒內生成不一樣的 ID。Snowflake 是 Twitter 開源的分布式 ID 生成算法,它不依賴數據庫。
核心思想是:分布式 ID 固定是一個 long 型的數字,一個 long 型占8個字節,也就是64個bit,原始 Snowflake 算法中對于 bit 的分配如下圖:
雪花算法
- 第1個 bit 位是標識部分,在 java 中由于 long 的最高位是符號位,正數是0,負數是1,一般生成的 ID 為正數,所以固定為0;
- 時間戳部分占41 bit,這個是毫秒級的時間,一般實現上不會存儲當前的時間戳,而是時間戳的差值(當前時間-固定的開始時間),這樣可以使產生的ID從更小值開始;41位的時間戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年;
- 工作機器id占10 bit,這里比較靈活,比如,可以使用前5位作為數據中心機房標識,后5位作為單機房機器標識,算下來可以部署1024個節點;
- 序列號部分占12 bit,支持同一毫秒內同一個節點可以生成4096個 ID
根據這個算法的邏輯,只需要將這個算法用編程語言實現出來,封裝為一個工具方法,那么各個業務應用可以直接使用該工具方法來獲取分布式 ID,我們只需保證每個業務應用有自己的工作機器 ID 即可,而不需要單獨去搭建獲取分布式 ID 的應用。
Snowflake 算法實現起來并不難,這里提供一個 Github 上的 Java 實現版本:SnowFlake
不過國內的很多大廠,其實并沒有直接使用 Snowflake 原始算法,多多少少都進行了改造,因為 Snowflake 算法中最難實踐的就是工作機器 Id,原始的 Snowflake 算法需要人工去為每臺機器指定一個機器 Id 并配置在某個地方,從而讓 Snowflake 可以從此處獲取機器 Id。但是對于大廠來說,機器是很多的,這樣做的人力成本太大,且容易出錯,因此才會對 Snowflake 進行改造。