分布式唯一ID生成器

2022-05-08 18:09:10 字數 1504 閱讀 5376

在應用程式中,經常需要全域性唯一的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萬個序列號,核心**:

1

private

static

synchronized

long nextid(long

epochsecond)

7if (lastepoch !=epochsecond)

11 offset++;

12long next = offset &max_next;

13if (next == 0)

17return

generateid(epochsecond, next, shard_id);

18 }

時間戳減去乙個固定值,此方案最高可支援到2023年。

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

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

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

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

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

分布式唯一id生成器的想法

前端時間遇到乙個問題,怎麼快速生成唯一的id,後來採用了hashid的方法。最近在網上讀到了美團關於分布式唯一id生成器的解決方案,其中提到了三種生成法 建議看一下這篇文章,寫得很詳細,分析到位 文中提到了如下幾個問題 美團針對上面的場景,作了兩種方案,leaf segment 資料庫方式 和lea...

分布式ID生成器

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