分布式全局唯一ID生成策略

本文到這里就結(jié)束了关面,喜歡的朋友可以幫忙轉(zhuǎn)發(fā)和關(guān)注一下,感謝支持十厢!

為了感謝支持我的朋友等太!整理了一份Java高級(jí)架構(gòu)資料、Spring源碼分析蛮放、Dubbo缩抡、Redis、Netty包颁、zookeeper瞻想、Spring cloud挎塌、分布式等資。

本號(hào)專注Java源碼分析内边。喜歡底層源碼的朋友可以來交流探討。交流群:818491202 驗(yàn)證:33

的需求待锈,它用于唯一標(biāo)識(shí)一個(gè)業(yè)務(wù)對(duì)象漠其、一個(gè)資源、或者一個(gè)消息等等竿音。在數(shù)據(jù)庫中和屎,唯一ID一般是用來做為一個(gè)數(shù)據(jù)的主鍵〈核玻看過前面介紹MySQL索引原理的文章的朋友應(yīng)該知道柴信,主鍵對(duì)于數(shù)據(jù)庫的重要性不言而喻。

在單機(jī)場(chǎng)景下宽气,要得到一個(gè)全局唯一的ID是非常容易的随常,你可以使用數(shù)據(jù)庫的自增功能

但是如果在分布式的場(chǎng)景下萄涯,想要構(gòu)建構(gòu)建一個(gè)全局唯一的ID就有些不一樣绪氛。因?yàn)榉植际较到y(tǒng)一般是高并發(fā)場(chǎng)景,那自然不適合使用單機(jī)數(shù)據(jù)庫的自增功能了涝影。如果你的技術(shù)選型恰好是MySQL這樣的“非分布式數(shù)據(jù)庫”枣察,那就得參考一下業(yè)界常見的分布式全局唯一ID生成策略了。

UUID

UUID全稱是Universally Unique Identifier燃逻,翻譯過來叫通用唯一識(shí)別碼序目。標(biāo)準(zhǔn)型式包含32個(gè)16進(jìn)制數(shù)字,以連字號(hào)分為五段伯襟,形式為8-4-4-4-12的36個(gè)字符猿涨,示例:9628f6e9-70ca-45aa-9f7c-77afe0d26e05,到目前為止業(yè)界一共有5種方式生成UUID姆怪,詳情見IETF發(fā)布的UUID規(guī)范《A Universally Unique IDentifier (UUID) URN Namespace》嘿辟,分別稱為UUID的5個(gè)版本。

在JDK自帶的UUID類可以產(chǎn)生版本3和版本4的UUID片效。所以這里簡(jiǎn)單介紹一下版本3和版本4的UUID的生成方式红伦。

UUID版本3:通過計(jì)算name和namespace的MD5散列值得到。

UUID版本4:根據(jù)隨機(jī)數(shù)淀衣,或者偽隨機(jī)數(shù)生成UUID昙读。這種UUID產(chǎn)生重復(fù)的概率是可以計(jì)算出來的,但是重復(fù)的可能性可以忽略不計(jì)膨桥,因此該版本也是被經(jīng)常使用的版本蛮浑。

也有在線生成UUID的網(wǎng)站唠叛,如果你的項(xiàng)目上用到了UUID,可以用來生成臨時(shí)的測(cè)試數(shù)據(jù)沮稚。www.uuidgenerator.net/

UUID的優(yōu)勢(shì)是實(shí)現(xiàn)起來很簡(jiǎn)單艺沼,用JDK原生的API即可得到。劣勢(shì)是與基于b-Tree引擎的數(shù)據(jù)庫的主鍵索引策略不太符合蕴掏,不適合作為高性能需求的場(chǎng)景下的數(shù)據(jù)庫主鍵障般。

基于Redis實(shí)現(xiàn)

都用分布式了,多半要上個(gè)緩存盛杰。用緩存的話挽荡,可能會(huì)使用Redis。Redis的INCR函數(shù)在單機(jī)上是原子操作即供,可以保證唯一且遞增定拟。

單機(jī)Redis可能無法支撐高并發(fā)。而如果使用Redis集群逗嫡,如何保證ID的唯一性呢青自?可以使用步長(zhǎng)的方式。比如有5個(gè)Redis節(jié)點(diǎn)組成的集群驱证,它們生成的ID分別為:

A: 1,6,11,16,21

B: 2,7,12,17,22

C: 3,8,13,18,23

D: 4,9,14,19,24

E: 5,10,15,20,25

類snowflake方案

Twitter利用Zookeeper實(shí)現(xiàn)了一個(gè)全局ID生成的服務(wù)snowflake性穿。其生成ID的數(shù)據(jù)結(jié)構(gòu)如下圖所示:

共64位,正好對(duì)應(yīng)Java中的long型雷滚,第一個(gè)符號(hào)位不用需曾,然后41位用于表示時(shí)間戳。后續(xù)10位用來表示節(jié)點(diǎn)的id祈远,如果是多機(jī)房節(jié)點(diǎn)呆万,可以劃分前5位用來表示機(jī)房id,后5位用來表示每個(gè)機(jī)房下的機(jī)器的id车份。最后12位用來表示序列號(hào)谋减,這樣可以做到同一毫秒,同一機(jī)器生成多個(gè)id扫沼,12位算下來最多支持4096個(gè)出爹。

這里的時(shí)間戳并不是當(dāng)前時(shí)間的Time Stamp,而是當(dāng)前時(shí)間相對(duì)于起始時(shí)間的差值缎除。如果基于毫秒來計(jì)算的話严就,41位大約可以用69年。

snowflake算法有許多變種器罐∩椅可以根據(jù)自己的實(shí)際情況調(diào)整位數(shù)的分配,比如時(shí)間戳占42位,機(jī)器id占9位铸董。42位時(shí)間戳就可以用138年等祟印。

百度的UidGenerator和美團(tuán)的Leaf都是基于snowflake的變種。

snowflake是一種比較好的生成ID方式粟害,保證全局唯一蕴忆,且支持高并發(fā)。而且是long類型的悲幅,趨勢(shì)遞增套鹅,可以用于數(shù)據(jù)庫主鍵。還可以根據(jù)時(shí)間來排序夺艰。

但也有其缺點(diǎn),就是強(qiáng)依賴服務(wù)器的時(shí)鐘沉衣,如果服務(wù)器的時(shí)鐘出現(xiàn)回?fù)埽ū热玳c秒或者NTP同步)郁副,就會(huì)導(dǎo)致ID重復(fù)。

美團(tuán)的Leaf解決了時(shí)鐘回?fù)艿膯栴}豌习,具體流程如下圖存谎,可以了解一下:

其他方式

當(dāng)然,還有一些其他的ID生成方案肥隆,比如:

滴滴:時(shí)間+起點(diǎn)編號(hào)+車牌號(hào)

淘寶訂單:時(shí)間戳+用戶ID

其他電商:時(shí)間戳+下單渠道+用戶ID既荚,有的會(huì)加上訂單第一個(gè)商品的ID。

MongoDB的ID:也算是類snowflake的一種栋艳。通過“時(shí)間+機(jī)器碼+pid+inc”共12個(gè)字節(jié)恰聘,4+3+2+3的方式最終標(biāo)識(shí)成一個(gè)24長(zhǎng)度的十六進(jìn)制字符。

總結(jié)

如果不用于數(shù)據(jù)庫主鍵吸占,建議直接用UUID晴叨。

如果想要用來做數(shù)據(jù)庫主鍵,又沒有使用分布式數(shù)據(jù)庫(比如TiDB矾屯、MongoDB等)兼蕊,可以考慮使用snowflake算法,建議使用美團(tuán)的Leaf件蚕。

數(shù)據(jù)庫中間件sharding-jdbc的分布式ID采用twitter開源的snowflake算法孙技,不需要依賴任何第三方組件,這樣其擴(kuò)展性和維護(hù)性得到最大的簡(jiǎn)化排作;但是snowflake算法的缺陷(強(qiáng)依賴時(shí)間牵啦,如果時(shí)鐘回?fù)埽蜁?huì)生成重復(fù)的ID)妄痪,sharding-jdbc沒有給出解決方案蕾久,如果用戶想要強(qiáng)化,需要自行擴(kuò)展。

關(guān)注公眾號(hào)領(lǐng)資料

搜索公眾號(hào)【Java耕耘者】,回復(fù)【Java】僧著,即可獲取大量?jī)?yōu)質(zhì)電子書和一份Java高級(jí)架構(gòu)資料履因、Spring源碼分析、Dubbo盹愚、Redis栅迄、Netty、zookeeper皆怕、Spring cloud毅舆、分布式等視頻資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市愈腾,隨后出現(xiàn)的幾起案子憋活,更是在濱河造成了極大的恐慌,老刑警劉巖虱黄,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悦即,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡橱乱,警方通過查閱死者的電腦和手機(jī)辜梳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泳叠,“玉大人作瞄,你說我怎么就攤上這事∥H遥” “怎么了宗挥?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)种蝶。 經(jīng)常有香客問我属韧,道長(zhǎng),這世上最難降的妖魔是什么蛤吓? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任宵喂,我火速辦了婚禮,結(jié)果婚禮上会傲,老公的妹妹穿的比我還像新娘锅棕。我一直安慰自己,他們只是感情好淌山,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布裸燎。 她就那樣靜靜地躺著,像睡著了一般泼疑。 火紅的嫁衣襯著肌膚如雪德绿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音移稳,去河邊找鬼蕴纳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛个粱,可吹牛的內(nèi)容都是我干的古毛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼都许,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼稻薇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起胶征,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤塞椎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后睛低,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體案狠,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年暇昂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了莺戒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伴嗡。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡急波,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘪校,到底是詐尸還是另有隱情澄暮,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布阱扬,位于F島的核電站泣懊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏麻惶。R本人自食惡果不足惜馍刮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窃蹋。 院中可真熱鬧卡啰,春花似錦、人聲如沸警没。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杀迹。三九已至亡脸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背浅碾。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工大州, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人及穗。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓摧茴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親埂陆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子苛白,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容