分布式情況下生成數(shù)據(jù)庫(kù)唯一ID的解決方案

id作為業(yè)務(wù)的唯一標(biāo)識(shí),在數(shù)據(jù)設(shè)計(jì)中屢見不鮮,例如:

?商品 —— product_id

?訂單 —— order_id

?消息 —— message_id

這些標(biāo)識(shí)往往就是數(shù)據(jù)庫(kù)的主鍵,mysql會(huì)在主鍵是建立聚簇索引,這個(gè)索引直接指向數(shù)據(jù)地址。相比普通索引指向聚簇索引,減少了一次索引查詢,速度很快。消息、訂單類似業(yè)務(wù)一般會(huì)有按照時(shí)間倒序查詢數(shù)據(jù)的需求,一種做法是在時(shí)間列上建立索引,更好的是依賴ID本身的插入有序性。所以,分布式ID需要滿足兩個(gè)核心條件:

?全局唯一

?時(shí)間趨勢(shì)有序

可能有人會(huì)說(shuō)了,直接用MySQL的auto_increment不就行了么。在創(chuàng)業(yè)初期的時(shí)候我也會(huì)選擇這個(gè)方案,簡(jiǎn)單、高效、快速——?jiǎng)?chuàng)業(yè)公司還是得快速迭代,盡快出產(chǎn)品,而且產(chǎn)品經(jīng)常變,花太多時(shí)間搞出的牛逼架構(gòu)說(shuō)不定不太用得上,浪費(fèi)了寶貴的時(shí)間。但這個(gè)方案是存在一些問(wèn)題的:

?影響并行插入——B記錄依賴A記錄的主鍵,需要等到A記錄插入成功,拿到A.id,才能插入B記錄

?數(shù)據(jù)恢復(fù)難度大——數(shù)據(jù)誤刪或者丟失后,由于日志中沒(méi)有ID,不能直接確定數(shù)據(jù)關(guān)聯(lián)性

?影響分庫(kù)分表——由于ID要插入后才知道,不能根據(jù)業(yè)務(wù)的主鍵進(jìn)行分庫(kù)分表

所以,在業(yè)務(wù)穩(wěn)定后,一定要抽出時(shí)間來(lái)還早期的技術(shù)債務(wù)。

常見方案

使用數(shù)據(jù)庫(kù)的auto_increment來(lái)生成唯一ID

優(yōu)點(diǎn)

?簡(jiǎn)單,使用已有功能,開發(fā)量小

?ID步長(zhǎng)固定

缺點(diǎn)

?寫入單點(diǎn),非高可用

?即使按照不同auto_increment起點(diǎn)擴(kuò)展多個(gè)主庫(kù),雖然提高了可用性,但卻不能保證ID的嚴(yán)格有序

?每次都需要訪問(wèn)數(shù)據(jù)庫(kù),容易到達(dá)性能天花板

批量拉取ID,逐一分配

這種方案也是將ID數(shù)據(jù)存入數(shù)據(jù)庫(kù),ID服務(wù)每次從數(shù)據(jù)庫(kù)中拉取N個(gè)ID,并將當(dāng)前已用ID最大值更新為原始數(shù)據(jù)+N,ID服務(wù)每次接到ID生成請(qǐng)求時(shí)就從這N個(gè)ID中依次返回。

優(yōu)點(diǎn)

?批量獲取,不用每次訪問(wèn)數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)壓力小

缺點(diǎn)

?整個(gè)服務(wù)還是單點(diǎn)

?服務(wù)宕機(jī)重啟會(huì)造成ID不連續(xù)

?無(wú)法水平擴(kuò)展

改進(jìn)

增加一套備用服務(wù),主服務(wù)掛了漂移到備用服務(wù)上,可以采用vip + keepalived或者增加proxy。

uuid

優(yōu)點(diǎn)

?本地生成ID,沒(méi)有單點(diǎn)問(wèn)題,沒(méi)有性能瓶頸

缺點(diǎn)

?不能保證遞增有序

?長(zhǎng)度過(guò)長(zhǎng),作為主鍵性能低

類snowflake算法

snowflake是twitter開源的分布式ID生成算法,其核心思想是:一個(gè)long型的ID,使用其中41bit作為毫秒數(shù),10bit作為機(jī)器編號(hào),12bit作為毫秒內(nèi)序列號(hào)。這個(gè)算法單機(jī)每秒內(nèi)理論上最多可以生成1000*(2^12),也就是400W的ID,完全能滿足業(yè)務(wù)的需求。

借鑒snowflake的思想,結(jié)合各公司的業(yè)務(wù)邏輯和并發(fā)量,可以實(shí)現(xiàn)自己的分布式ID生成算法。

優(yōu)點(diǎn)

?時(shí)間在高位,趨勢(shì)遞增

?實(shí)現(xiàn)簡(jiǎn)單,不依賴其它服務(wù),方便擴(kuò)展

缺點(diǎn)

?沒(méi)有全局時(shí)鐘,單機(jī)絕對(duì)有序,但從整個(gè)集群來(lái)看,是趨勢(shì)有序的

注意事項(xiàng)

?由于ID常作為分庫(kù)分表的標(biāo)識(shí),所以需要這些ID有一定的隨機(jī)性,不至于分庫(kù)后的數(shù)據(jù)不均勻,可以在每個(gè)毫秒開始時(shí)序列號(hào)不從1開始,二是從0-9中的任意一個(gè)開始

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊10 分享