如何生成全局唯一id

為什么需要全局唯一id

在分布式架構(gòu)下,經(jīng)常有需求需要生成全局唯一id,比如優(yōu)惠券等券碼,或者分庫(kù)分表,每個(gè)表都用自增id,會(huì)導(dǎo)致每個(gè)表的id都不唯一,都需要生成全局唯一id。
這里介紹幾種分布式架構(gòu)下全局唯一id的生成方式,然后再結(jié)合具體場(chǎng)景說(shuō)下實(shí)際項(xiàng)目中遇到哪些問(wèn)題和解決方案,最后介紹下美團(tuán)的全局唯一id生成服務(wù)leaf的實(shí)現(xiàn)。

常用解決方案

一、UUID

這是最容易想到的方案,UUID(Universally Unique Identifier)是32個(gè)16進(jìn)制數(shù)字,以連字號(hào)分為五段,形式為8-4-4-4-12的36個(gè)字符,目前生成方式有5種,可參考A Universally Unique IDentifier (UUID) URN Namespace
好處就是生成很簡(jiǎn)單,每個(gè)系統(tǒng)本地生成就可以。
壞處更加明顯,就是太長(zhǎng)和無(wú)序,會(huì)導(dǎo)致以下問(wèn)題:
1、很多業(yè)務(wù)場(chǎng)景不適用,比如優(yōu)惠券的發(fā)放,可能12位的券池就能滿足發(fā)放的需要了,太長(zhǎng)不但不易于存儲(chǔ),還會(huì)導(dǎo)致無(wú)法用于券碼的展示
2、不利于做索引。mysql存儲(chǔ)時(shí),uuid的長(zhǎng)度太長(zhǎng)不利于做主鍵,而且無(wú)序性會(huì)導(dǎo)致作為主鍵插入時(shí)數(shù)據(jù)位置頻繁變動(dòng),影響性能
所以,很多場(chǎng)景或者用于主鍵的情況下,都不能使用uuid

二、數(shù)據(jù)庫(kù)自增主鍵

可以創(chuàng)建一個(gè)表,通過(guò)數(shù)據(jù)插入獲取對(duì)應(yīng)的自增主鍵,作為全局唯一id
缺點(diǎn)也很明顯,就是高并發(fā)的場(chǎng)景下,受限于單臺(tái)mysql的性能。而且可用性差,DB出現(xiàn)問(wèn)題會(huì)導(dǎo)致id無(wú)法生成。
當(dāng)然可以通過(guò)主從的方式增強(qiáng)可用性,同時(shí)增加表采用不同自增步長(zhǎng)的方式增加并發(fā)性能,比如假設(shè)我們要部署N臺(tái)機(jī)器,步長(zhǎng)需設(shè)置為N,每臺(tái)的初始值依次為0,1,2…N-1;但是還會(huì)帶來(lái)新的問(wèn)題,比如不利于拓展,想提升性能就要堆機(jī)器,但是步長(zhǎng)已經(jīng)確定不好更改,主從延遲會(huì)導(dǎo)致唯一id的不唯一,。

三、snowflake

這是twitter開源的分布式id生成算法,這種方案把64-bit分別劃分成多段,分開來(lái)標(biāo)示機(jī)器、時(shí)間等,比如在snowflake中的64-bit分別表示如下圖(圖片來(lái)自網(wǎng)絡(luò))所示:


image.png

上面第一個(gè)部分,是1個(gè)bit:0,這個(gè)是無(wú)意義的上面第二個(gè)部分是41個(gè)bit:表示的是時(shí)間戳;上面第三個(gè)部分是5個(gè)bit:表示的是機(jī)房id,10001上面第四個(gè)部分是5個(gè)bit:表示的是機(jī)器id,1 1001上面第五個(gè)部分是12個(gè)bit:表示的序號(hào),就是某個(gè)機(jī)房某臺(tái)機(jī)器上這一毫秒內(nèi)同時(shí)生成的id的序號(hào),0000 00000000
優(yōu)點(diǎn)就是靈活,5位可以用來(lái)做業(yè)務(wù)標(biāo)識(shí)
缺點(diǎn)呢就是比較依賴時(shí)鐘

實(shí)際應(yīng)用

場(chǎng)景一:分庫(kù)分表后數(shù)據(jù)唯一id

需求:

  • id要作為主鍵,即要滿足趨勢(shì)遞增
  • id長(zhǎng)度盡量小
    這種場(chǎng)景我們?cè)陧?xiàng)目中使用了數(shù)據(jù)庫(kù)自增主鍵的方式,創(chuàng)建了32張表,步長(zhǎng)32并設(shè)置遞增初始值的方式,生成唯一id,可以較好的滿足該場(chǎng)景。

場(chǎng)景二:團(tuán)購(gòu)券券碼

需求:

  • 券碼唯一且不能趨勢(shì)遞增,不然用戶會(huì)猜測(cè)券碼,不安全
  • 券碼長(zhǎng)度控制在可接受范圍
    這種場(chǎng)景項(xiàng)目中用了碰撞的方式,隨機(jī)生成的固定長(zhǎng)度券碼保存在券碼表,券碼唯一索引,job定時(shí)補(bǔ)充券碼表并撈取可用券碼到緩存券池。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容