2024-01-21 分類: 網(wǎng)站建設(shè)
我們目前主流的服務(wù)端系統(tǒng)都是分布式的架構(gòu)。業(yè)務(wù)分布在不同的機器節(jié)點上產(chǎn)生數(shù)據(jù),數(shù)據(jù)也存儲在不同的機器節(jié)點。為了方便標(biāo)識數(shù)據(jù),我們使用 唯一且有序 的ID來標(biāo)識數(shù)據(jù)。即:
整個分布式系統(tǒng)中,新生成的ID永遠不會產(chǎn)生與之前已經(jīng)生成的ID重復(fù);
生成的所有ID可以根據(jù)生成的時間進行排序(生成時間晚的排序順序靠后)
我們來看一下市面上的幾種主流的ID生成方案。
一、Mysql 集群
由于我們的討論前提是分布式架構(gòu)的系統(tǒng),所以這里的 Mysql 我們默認是集群版。
眾所周知,Mysql 有自帶的唯一ID機制,即自增主鍵,可以保證在同一個數(shù)據(jù)庫中,表內(nèi)生成的每一條記錄都是唯一且有序的。
但是如果放在分布式系統(tǒng)里面,我們用分庫/分表的架構(gòu)存儲記錄,那就會導(dǎo)致在系統(tǒng)中產(chǎn)生重復(fù)的ID。
如下圖,表1 2 3都是存儲相同記錄的不同表(可以在同一個數(shù)據(jù)庫里,也可以在不同數(shù)據(jù)庫里),表1 2 3都會產(chǎn)生id相同的數(shù)據(jù)。
為了解決這個問題,mysql 官方支持數(shù)據(jù)庫 ID 生成時設(shè)置步長,可以保證不同數(shù)據(jù)庫中相同表的id唯一性。
如上圖,每個表都有 不同的起始id和相同的步長 ,這就能保證業(yè)務(wù)記錄Id的唯一性。
設(shè)置步長的方案雖然解決了id生成的唯一性,但是也有很大的缺點
不能保證ID的有序性和時間的強相關(guān)。(由于是分布式系統(tǒng),不能保證id=4的數(shù)據(jù)一定在id=3的數(shù)據(jù)后面生成)
每次新增加一個節(jié)點,要重置所有節(jié)點的起始值和步長。
第二點只是數(shù)據(jù)庫管理會麻煩一些,但是第一點不能滿足我們對有序性的要求。
二、ID數(shù)據(jù)庫
這里泛指一套單獨維護的ID數(shù)據(jù)庫,目的是為了保證業(yè)務(wù)系統(tǒng)內(nèi)所有的ID的唯一性和有序性。
舉幾個例子,比如Mysql維護一條表記錄,Redis 維護一個key,zookeeper 維護一個序列號。當(dāng)所有業(yè)務(wù)都通過調(diào)用這些存儲服務(wù)來生成+獲取唯一ID的時候,就可以保證生成Id的唯一性和有序性。
缺點:
需要資源單獨維護一個服務(wù)
如果ID數(shù)據(jù)庫掛掉,整個業(yè)務(wù)就會停擺。如果ID數(shù)據(jù)庫出現(xiàn)數(shù)據(jù)錯亂,可能會影響到唯一性和有序性
總結(jié)一下就是,ID數(shù)據(jù)庫可以提供唯一有序的ID,但是有一定的維護成本且系統(tǒng)的風(fēng)險很高。
三、雪花算法
SnowFlake是Twitter公司采用的一種算法,目的是在分布式系統(tǒng)中產(chǎn)生 全局唯一且整體遞增 的ID。
3.1 生成ID的結(jié)構(gòu)
3.2 生成原理
我們先看一下雪花ID的生成過程:
生成毫秒級別的時間戳,填充到 41bit 的位置
序列號默認為 000000000000 。如果 新生成的時間戳上次生成的相等 ,序列號就會 + 1。將序列號填充到 12bit 位置
存儲當(dāng)前生成的時間戳到內(nèi)存中,以便下次生成時判斷
獲取到當(dāng)前機器+進程的唯一標(biāo)識,填充到 10bit 的位置
通過上述整個流程我們可以看到,雪花算法可以確保唯一性,單機內(nèi)在同一毫秒生成的ID會有序列號的遞增,多機環(huán)境在同一毫秒生成的ID會有機器+進程的唯一標(biāo)識。
但是無法保證強有序性,比如多個機器在同一毫秒內(nèi)生成的ID,就無法按照時間規(guī)則進行排序
3.3 缺點
雪花算法除了無法實現(xiàn)嚴(yán)格按照時間的有序性之外,還有一個可能存在的風(fēng)險點,就是 單機時鐘回撥 。
如果一個機器之前已經(jīng)生成過ID,將機器的時間改為之前的時間,那么就有一定幾率會生成與之前相同的ID。
四、mongoDB 的唯一ID生成策略
mongo唯一ID生成策略——ObjectId,和雪花算法相似度極高。區(qū)別在于雪花算法要占用64個字節(jié),而 ObjectId 只需要占用 12個字節(jié),但是objectId只能存儲秒級別時間戳。
ObjectId如果用字符串表示則有24個字符,但實際上它是由一組十六進制的字符構(gòu)成,每個字節(jié)兩位的十六進制數(shù)字,總共用了12字節(jié)的存儲空間。
比如:6331500a7cac81af7136236b 這個ID
秒級時間戳
機器碼
進程的pid
序號
mongoDB 的 ObjectId 和雪花算法一樣,無法實現(xiàn)嚴(yán)格按照時間的有序性,并且由于是秒級別的時間戳,所以不同機器生成的ID,不按照時間排序的可能性會大很多。而且如果單機時鐘回撥,也會產(chǎn)生與之前重復(fù)的ID。
總結(jié)
特性/方案 | Mysql 集群 | ID數(shù)據(jù)庫 | 雪花算法 | mongoDB ObjectId |
---|---|---|---|---|
唯一性 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
按照生成時間的有序性 | :x: | :white_check_mark: | :x: | :x: |
維護的難易程度 | 難 | 較難 | 易維護 | 易維護 |
在分布式系統(tǒng)中:
以上四種方案都可以保證生成ID的唯一性
如果并發(fā)量很小的系統(tǒng),可以考慮 雪花算法/mongoDB ObjectId 方案來保證有序性
如果并發(fā)量很大,只能用ID數(shù)據(jù)庫來保證有序性,但是會比 雪花算法/mongoDB ObjectId 方案增加維護成本?
網(wǎng)站標(biāo)題:mysql多條數(shù)據(jù)存到不同表id唯一分布式系統(tǒng)中的唯一ID生成
地址分享:http://jinyejixie.com/news10/314710.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、軟件開發(fā)、網(wǎng)站設(shè)計公司、面包屑導(dǎo)航、網(wǎng)站排名、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容