應用id 分布式唯一ID生成器

2021-10-14 14:47:16 字數 1442 閱讀 8716

在應用程式中,經常需要全域性唯一的id作為資料庫主鍵。如何生成全域性唯一id?

首先,需要確定全域性唯一id是整型還是字串?如果是字串,那麼現有的uuid就完全滿足需求,不需要額外的工作。缺點是字串作為id占用空間大,索引效率比整型低。

如果採用整型作為id,那麼首先排除掉32位int型別,因為範圍太小,必須使用64位long型。

採用整型作為id時,如何生成自增、全域性唯一且不重複的id?

方案一:利用資料庫的自增id,從1開始,基本可以做到連續遞增。oracle可以用sequence,mysql可以用主鍵的auto_increment,雖然不能保證全域性唯一,但每個表唯一,也基本滿足需求。

資料庫自增id的缺點是資料在插入前,無法獲得id。資料在插入後,獲取的id雖然是唯一的,但一定要等到事務提交後,id才算是有效的。有些雙向引用的資料,不得不插入後再做一次更新,比較麻煩。

第二種方式是採用乙個集中式id生成器,它可以是redis,也可以是zookeeper,也可以利用資料庫的表記錄最後分配的id。

這種方式最大的缺點是複雜性太高,需要嚴重依賴第三方服務,而且**配置繁瑣。一般來說,越是複雜的方案,越不可靠,並且測試越痛苦。

第三種方式是類似twitter的snowflake演算法,它給每台機器分配乙個唯一標識,然後通過時間戳+標識+自增實現全域性唯一id。這種方式好處在於id生成演算法完全是乙個無狀態機,無網路呼叫,高效可靠。缺點是如果唯一標識有重複,會造成id衝突。

snowflake演算法採用41bit毫秒時間戳,加上10bit機器id,加上12bit序列號,理論上最多支援1024臺機器每秒生成4096000個序列號,對於twitter的規模來說夠用了。

但是對於絕大部分普通應用程式來說,根本不需要每秒超過400萬的id,機器數量也達不到1024臺,所以,我們可以改進一下,使用更短的id生成方式:

53bitid由32bit秒級時間戳+16bit自增+5bit機器標識組成,累積32臺機器,每秒可以生成6.5萬個序列號,核心**:

private static synchronized long nextid(long epochsecond)     if (lastepoch != epochsecond)     offset++;    long next = offset & max_next;    if (next == 0)     return generateid(epochsecond, next, shard_id);}
時間戳減去乙個固定值,此方案最高可支援到2023年。

如果每秒6.5萬個序列號不夠怎麼辦?沒關係,可以繼續遞增時間戳,向前「借」下一秒的6.5萬個序列號。

同時還解決了時間回撥的問題。

機器標識採用簡單的主機名方案,只要主機名符合host-1,host-2就可以自動提取機器標識,無需配置。

分布式唯一ID生成器

在應用程式中,經常需要全域性唯一的id作為資料庫主鍵。如何生成全域性唯一id?首先,需要確定全域性唯一id是整型還是字串?如果是字串,那麼現有的uuid就完全滿足需求,不需要額外的工作。缺點是字串作為id占用空間大,索引效率比整型低。如果採用整型作為id,那麼首先排除掉32位int型別,因為範圍太小...

分布式ID生成器

一 需求緣起 幾乎所有的業務系統,都有生成乙個唯一記錄標識的需求,例如 這個記錄標識往往就是資料庫中的主鍵,資料庫上會建立聚集索引 cluster index 即在物理儲存上以這個字段排序。這個記錄標識上的查詢,往往又有分頁或者排序的業務需求,例如 所以往往要有乙個time欄位,並且在time欄位上...

分布式 ID 生成器

乙個唯一 id 在乙個分布式系統中是非常重要的乙個業務屬性,其中包括一些如訂單 id,訊息 id 會話 id,他們都有一些共有的特性 全域性唯一很好理解,目的就是唯一標識某個次請求,某個業務。通常有以下幾種方案 可以利用mysql中的自增屬性auto increment來生成全域性唯一 id,也能保...