業(yè)界實(shí)現(xiàn)方案
1. 基于UUID
2. 基于DB數(shù)據(jù)庫(kù)多種模式(自增主鍵、segment)
3. 基于Redis
4. 基于ZK、ETCD
5. 基于SnowFlake
6. 美團(tuán)Leaf(DB-Segment、zk+SnowFlake)
7. 百度uid-generator()
1.基于UUID生成唯一ID
UUID:
UUID長(zhǎng)度128bit,32個(gè)16進(jìn)制字符,占用存儲(chǔ)空間多,且生成的ID是無(wú)序的;
對(duì)于InnoDB這種聚集主鍵類型的引擎來(lái)說(shuō),數(shù)據(jù)會(huì)按照主鍵進(jìn)行排序,由于UUID的無(wú)序性,InnoDB會(huì)產(chǎn)生巨大的IO壓力,此時(shí)不適合使用UUID做物理主鍵,可以把它作為邏輯主鍵,物理主鍵依然使用自增ID。
組成部分:
為了保證UUID的唯一性,規(guī)范定義了包括網(wǎng)卡MAC地址,時(shí)間戳,名字空間,隨機(jī)或偽隨機(jī)數(shù),時(shí)序等元素.
優(yōu)點(diǎn):
性能非常高:本地生成,沒(méi)有網(wǎng)絡(luò)消耗。
缺點(diǎn):
不易于存儲(chǔ):UUID太長(zhǎng),16字節(jié)128位,通常以36長(zhǎng)度的字符串表示,很多場(chǎng)景不適用
信息不安全:基于MAC地址生成UUID的算法可能會(huì)造成MAC地址泄露,這個(gè)漏洞曾被用于尋找梅麗莎病毒的制作者位置
ID作為主鍵時(shí)在特定的環(huán)境會(huì)存在一些問(wèn)題,比如做DB主鍵的場(chǎng)景下,UUID就非常不適用:
UUID生成策略?
UUID Version 1:基于時(shí)間的UUID
基于時(shí)間的UUID通過(guò)計(jì)算當(dāng)前時(shí)間戳、隨機(jī)數(shù)和機(jī)器MAC地址得到。由于在算法中使用了MAC地址,這個(gè)版本的UUID可以保證在全球范圍的唯一性。但與此同時(shí),使用MAC地址會(huì)帶來(lái)安全性問(wèn)題,這就是這個(gè)版本UUID受到批評(píng)的地方。如果應(yīng)用只是在局域網(wǎng)中使用,也可以使用退化的算法,以IP地址來(lái)代替MAC地址--Java的UUID往往是這樣實(shí)現(xiàn)的(當(dāng)然也考慮了獲取MAC的難度)
UUID Version 2:DCE安全的UUID
DCE(Distributed Computing Environment)安全的UUID和基于時(shí)間的UUID算法相同,但會(huì)把時(shí)間戳的前4位置換為POSIX的UID或GID。這個(gè)版本的UUID在實(shí)際中較少用到。
UUID Version 3:基于名字的UUID(MD5)
基于名字的UUID通過(guò)計(jì)算名字和名字空間的MD5散列值得到。這個(gè)版本的UUID保證了:相同名字空間中不同名字生成的UUID的唯一性;不同名字空間中的UUID的唯一性;相同名字空間中相同名字的UUID重復(fù)生成是相同的。
UUID Version 4:隨機(jī)UUID
根據(jù)隨機(jī)數(shù),或者偽隨機(jī)數(shù)生成UUID。這種UUID產(chǎn)生重復(fù)的概率是可以計(jì)算出來(lái)的,但隨機(jī)的東西就像是買彩票:你指望它發(fā)財(cái)是不可能的,但狗屎運(yùn)通常會(huì)在不經(jīng)意中到來(lái)。
UUID Version 5:基于名字的UUID(SHA1)
和版本3的UUID算法類似,只是散列值計(jì)算使用SHA1(Secure Hash Algorithm 1)算法
?
UUID應(yīng)用
UUID Version 1:基于時(shí)間的UUID
從UUID的不同版本可以看出
? Version 1/2適合應(yīng)用于分布式計(jì)算環(huán)境下,具有高度的唯一性?? Version 3/5適合于一定范圍內(nèi)名字唯一,且需要或可能會(huì)重復(fù)生成UUID的環(huán)境下?? 至于Version 4,建議是最好不用(雖然它是最簡(jiǎn)單最方便的)?? 通常我們建議使用UUID來(lái)標(biāo)識(shí)對(duì)象或持久化數(shù)據(jù),但以下情況最好不使用UUID:? 映射類型的對(duì)象。比如只有代碼及名稱的代碼表。? 人工維護(hù)的非系統(tǒng)生成對(duì)象。比如系統(tǒng)中的部分基礎(chǔ)數(shù)據(jù)。? 對(duì)于具有名稱不可重復(fù)的自然特性的對(duì)象,最好使用Version 3/5的UUID。比如系統(tǒng)中的用戶。如果用戶的UUID是Version 1的,如果你不小心刪除了再重建用戶,你會(huì)發(fā)現(xiàn)人還是那個(gè)人,用戶已經(jīng)不是那個(gè)用戶了。(雖然標(biāo)記為刪除狀態(tài)也是一種解決方案,但會(huì)帶來(lái)實(shí)現(xiàn)上的復(fù)雜性。
?
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-663337.html
2.基于DB數(shù)據(jù)庫(kù)多種模式(自增主鍵、segment)
基于DB的自增主鍵方案?
實(shí)現(xiàn)原理:
基于MySQL,最簡(jiǎn)單的方法是使用auto_increment 來(lái)生成全局唯一遞增ID,但最致命的問(wèn)題是在高并發(fā)情況下,數(shù)據(jù)庫(kù)壓力大,DB單點(diǎn)存在宕機(jī)風(fēng)險(xiǎn)
優(yōu)點(diǎn):
實(shí)現(xiàn)簡(jiǎn)單、基于數(shù)據(jù)庫(kù)底層機(jī)制
缺點(diǎn):
高并發(fā)情況下,數(shù)據(jù)庫(kù)壓力大,DB單點(diǎn)存在宕機(jī)風(fēng)險(xiǎn)
?
?
基于DB多主模式方案
在分布式系統(tǒng)中我們可以多部署幾臺(tái)機(jī)器,
每臺(tái)機(jī)器設(shè)置不同的初始值,且步長(zhǎng)和機(jī)器數(shù)相等。
比如有兩臺(tái)機(jī)器。設(shè)置步長(zhǎng)step為2,
TicketServer1的初始值為1(1,3,5,7,9,11…)、
TicketServer2的初始值為2(2,4,6,8,10…)。
這是Flickr團(tuán)隊(duì)在2010年撰文介紹的一種主鍵生成策略
(Ticket Servers: Distributed Unique Primary Keys on the Cheap )
如下所示,為了實(shí)現(xiàn)上述方案分別設(shè)置兩臺(tái)機(jī)器對(duì)應(yīng)的參數(shù),
TicketServer1從1開(kāi)始發(fā)號(hào),
TicketServer2從2開(kāi)始發(fā)號(hào),
兩臺(tái)機(jī)器每次發(fā)號(hào)之后都遞增2
?
基于DB號(hào)段實(shí)現(xiàn)方案
實(shí)現(xiàn)原理:
每次向db申請(qǐng)一個(gè)號(hào)段,加載到內(nèi)存中,然后采用自增的方式來(lái)生成id,這個(gè)號(hào)段用完后,再次向db申請(qǐng)一個(gè)新的號(hào)段,這樣對(duì)db的壓力就減輕了很多,同時(shí)內(nèi)存中直接生成id。向數(shù)據(jù)庫(kù)申請(qǐng)新號(hào)段,對(duì)max_id字段做一次update操作,update max_id= max_id + step,update成功則說(shuō)明新號(hào)段獲取成功,新的號(hào)段范圍是(max_id ,max_id +step]。
優(yōu)點(diǎn):
利用了緩存,減輕DB壓力,性能提升
缺點(diǎn):
依然存在DB模式下的性能瓶頸,ID最大值的限制
?
3.基于Redis實(shí)現(xiàn)分布式ID?
- 因?yàn)?/span>Redis是單線程的,所以天然沒(méi)有資源爭(zhēng)用問(wèn)題,可以采用 incr 指令,實(shí)現(xiàn)ID的原子性自增。
- 但是因?yàn)?/span>Redis的數(shù)據(jù)備份-RDB,會(huì)存在漏掉數(shù)據(jù)的可能,所以理論上存在已使用的ID再次被使用,所以備份方式可以加上AOF方式,這樣的話性能會(huì)有所損耗。
?
4.基于Zookeeper實(shí)現(xiàn)分布式ID
原理:
利用zookeeper中的順序節(jié)點(diǎn)的特性,制作分布式的序列號(hào)生成器(ID生成器)
5.基于ETCD實(shí)現(xiàn)分布式ID?
原理:
每個(gè)tx事務(wù)有唯一事務(wù)ID,在etcd中叫做main ID,全局遞增不重復(fù)。一個(gè)tx可以包含多個(gè)修改操作(put和delete),每一個(gè)操作叫做一個(gè)revision(修訂),共享同一個(gè)main ID。
一個(gè)tx內(nèi)連續(xù)的多個(gè)修改操作會(huì)被從0遞增編號(hào),這個(gè)編號(hào)叫做sub ID。
每個(gè)revision由(main ID,sub ID)唯一標(biāo)識(shí)。
6.美團(tuán)Leaf-基于ZK的SnowFlake算法?
Leaf-snowflake方案完全沿用snowflake方案的bit位設(shè)計(jì).
即是“1+41+10+12”的方式組裝ID號(hào)。
對(duì)于workerID的分配,當(dāng)服務(wù)集群數(shù)量較小的情況下,完全可以手動(dòng)配置。
Leaf服務(wù)規(guī)模較大,動(dòng)手配置成本太高。所以使用Zookeeper持久順序節(jié)點(diǎn)的特性
自動(dòng)對(duì)snowflake節(jié)點(diǎn)配置wokerID
?
7.百度uid-generator分布式ID生成器
UidGenerator是Java實(shí)現(xiàn)的, 基于Snowflake算法的唯一ID生成器。
UidGenerator以組件形式工作在應(yīng)用項(xiàng)目中, 支持自定義workerId位數(shù)和初始化策略,
從而適用于docker等虛擬化環(huán)境下實(shí)例自動(dòng)重啟、漂移等場(chǎng)景。
?在實(shí)現(xiàn)上, UidGenerator通過(guò)借用未來(lái)時(shí)間來(lái)解決sequence天然存在的并發(fā)限制;
采用RingBuffer來(lái)緩存已生成的UID, 并行化UID的生產(chǎn)和消費(fèi), 同時(shí)對(duì)CacheLine補(bǔ)齊,
避免了由RingBuffer帶來(lái)的硬件級(jí)「?jìng)喂蚕怼箚?wèn)題. 最終單機(jī)QPS可達(dá)600萬(wàn)。
其實(shí)現(xiàn)原理和雪花算法并無(wú)二致,自定義號(hào)段,并且采用RingBuffer作為緩沖從而提升性能。詳見(jiàn)官網(wǎng)地址:
https://github.com/baidu/uidgenerator/blob/master/README.zh_cn.md文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-663337.html
?
到了這里,關(guān)于【業(yè)務(wù)功能篇73】分布式ID解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!