深圳手機(jī)網(wǎng)站制作公司全網(wǎng)搜索軟件
為了保證全局唯一性可以用時間作為區(qū)分點(diǎn)一部分,時間盡可能細(xì)化,可以精確到毫秒,甚至是微秒和納秒。如果是分布式系統(tǒng)有多態(tài)機(jī)器,可以根據(jù)機(jī)器ID再進(jìn)行以下區(qū)分。如哦機(jī)器運(yùn)行的特別快,1毫秒有大量ID生成,可以結(jié)合實(shí)際限制下實(shí)際生成的ID數(shù)目。
如果N臺機(jī)器去ID生成服務(wù)器的服務(wù)端得到全局ID,很容易保證全局唯一切自增的,但是存在單點(diǎn)失效的問題,不滿足高可用。
雪花算法
生成的結(jié)果是一個int64
的數(shù)據(jù)。核心思想是:使用41bit作為毫秒數(shù),10bit作為機(jī)器的ID(5個bit是數(shù)據(jù)中心,5個bit的機(jī)器ID),12bit作為毫秒內(nèi)的流水號,意味著每個節(jié)點(diǎn)再每毫秒可以產(chǎn)生 4096 個 ID, 最后還有一個符號位,永遠(yuǎn)是0.
優(yōu)點(diǎn): 優(yōu)點(diǎn)是毫秒書在高位,自增序列在低位,整個ID是趨勢遞增的。不依賴數(shù)據(jù)庫等第三方系統(tǒng),一服務(wù)的方式部署,穩(wěn)定性更高,生成ID的性能也是非常高的。可以根據(jù)自身業(yè)務(wù)特性分配bit位,非常靈活。
缺點(diǎn): 強(qiáng)依賴機(jī)器時鐘,如果機(jī)器上時鐘回?fù)?#xff0c;會導(dǎo)致號重復(fù)或者服務(wù)會處于不可用狀態(tài)。
Redis生成ID
因為 Redis 是單線程的,也可以用來生成全局唯一ID??梢杂肦edis的原子操作INCR和INCRBY來實(shí)現(xiàn)。使用Redis集群來獲取更高的吞吐量。假如一個集群中有5臺Redis,可以初始化每臺Redis的值分別是1,2,3,4,5,步長都是5,各Redis生成的ID如下:A: 1,6,11,16; B: 2,7,12,17; C: 3,8,13,18; D: 4,9,14,19; E: 5,10,15,29。負(fù)載到哪臺機(jī)器提前定好,未來很難做修改。3-5臺服務(wù)器基本能安祖需求,但步長和初始值一定需要事先確定,使用Redis集群也可以解決單點(diǎn)故障問題。
**優(yōu)點(diǎn):**不依賴數(shù)據(jù)庫,靈活方便,且性能優(yōu)于數(shù)據(jù)庫,數(shù)字ID天然排序,對分頁或需要排序的結(jié)果很有幫助。
**缺點(diǎn):**如果系統(tǒng)中沒有Redis,需要引入新的組件,增加系統(tǒng)復(fù)雜度;需要編碼和配置的工作量比較大。
UUID
可以利用數(shù)據(jù)庫也可以利用程序生成,一般全球唯一。UUID是由32個16進(jìn)制數(shù)字組成,所以每個UUID的長度是128位(16^32 = 2 ^128)。UUID有多個實(shí)現(xiàn)版本,影響它的因素包括時間,網(wǎng)卡MAC地址,自定義Namespace等等。
優(yōu)點(diǎn):簡單,代碼方便;生成ID性能非常好,基本不會有性能問題;全球唯一,在遇見數(shù)據(jù)遷移,系統(tǒng)數(shù)據(jù)合并,或者數(shù)據(jù)庫變更情況下,可以從容應(yīng)對。
缺點(diǎn):沒有排序,無法保證確實(shí)遞增;UUID往往是使用字符串存儲,查詢的效率比較低;存儲空間比較大,如果是海量數(shù)據(jù)庫,就需要哦考慮存儲量的問題;傳輸數(shù)據(jù)量大;不可讀。
美團(tuán)Leaf
Leaf-segment
直接用數(shù)據(jù)庫自增ID充當(dāng)分布式ID,減少對數(shù)據(jù)庫的頻繁操作。過程是從數(shù)據(jù)庫批量的獲取自增ID,每次從數(shù)據(jù)庫取出一個號段范圍,例如(1,10000]代表10000個ID,業(yè)務(wù)服務(wù)將號段生成1~10000的自增ID并加載在內(nèi)存,在當(dāng)前號段消費(fèi)到某個點(diǎn)時,就異步的把下一個號段加載到內(nèi)存中。而不需要等到號段用盡的時候才去更新號段。這樣做很大程度上的降低了系統(tǒng)的風(fēng)險。Leaf-segment采用雙buffer的發(fā)過誓,他的服務(wù)內(nèi)部有兩個號段緩存qusegment.當(dāng)前號段已消耗10%時,還沒能拿到下一個號段,則會另啟一個更新線程去更新下一個號段。Leaf保證了總是會多緩存兩個號段,即便那一時刻數(shù)據(jù)庫掛了,也會保證發(fā)號服務(wù)可以正常工作一段時間。通常推薦號段(segment)長度設(shè)置為服務(wù)高峰期發(fā)號QPS的600倍(10分鐘),這樣即使DB宕機(jī),Leaf仍能持續(xù)發(fā)號10-20分鐘不受影響。
tip biz_tag
針對不同業(yè)務(wù)需求,用biz_tag字段來隔離,如果以后需要擴(kuò)容時,只需要對biz_tag分庫分表即可
優(yōu)點(diǎn): Leaf服務(wù)可以很方便的線性擴(kuò)展,性能完全能夠支持大多數(shù)業(yè)務(wù)場景;容災(zāi)行=性高;Leaf服務(wù)內(nèi)部有號段緩存,即使DB宕機(jī),短時間內(nèi)Leaf仍能正常對外提供服務(wù)。
缺點(diǎn): ID號碼不夠隨機(jī),能夠泄漏發(fā)號數(shù)量的信息,不太安全;DB宕機(jī)會造成整個系統(tǒng)不可用(用到數(shù)據(jù)庫的都有可能)
Leaf-snowflake
Leaf-snowflake基本上就是沿用了snowflake的設(shè)計,ID組成結(jié)構(gòu):正數(shù)位(占1比特)+時間戳(占41比特)+機(jī)器ID(占5bit)+機(jī)房ID(占5 bit) + 自增值(占12bit), 總共54比特組成的一個int64類型。不同點(diǎn)主要是在workId的生成上,Leaf-snowflake依靠Zookeerper生成workId。Leaf中workId時基于Zookeeper中生成一個順序Id,相當(dāng)于一臺機(jī)器對應(yīng)一個順序節(jié)點(diǎn)。
啟動服務(wù)的過程大致如下:啟動Leaf-snowflake服務(wù),連接Zookeeper, 在leaf_foever父節(jié)點(diǎn)下檢查自己是否已經(jīng)注冊過;如果有注冊過直接取回自己的workerId(zk順序節(jié)點(diǎn)生成的int類型ID號)。啟動服務(wù);如果沒有注冊過,就在該父節(jié)點(diǎn)下面創(chuàng)建一個持久順序節(jié)點(diǎn),創(chuàng)建成功后取回順序號當(dāng)作自己的workerID號,啟動服務(wù)。Leaf-snowflake對Zookeeper是一種弱依賴關(guān)系,除了每次會去ZK拿數(shù)據(jù)以外,也會在本機(jī)文件系統(tǒng)上緩存一個workerID文件。一旦Zookeeper出現(xiàn)問題,敲好機(jī)器出現(xiàn)故障需重啟時,依然能夠保證服務(wù)正常啟動。
優(yōu)點(diǎn): ID號碼是趨勢遞增的8 byte的64位數(shù)據(jù),滿足上述數(shù)據(jù)庫存儲的主鍵要求。
缺點(diǎn): 依賴Zookeeper, 存在服務(wù)不可用風(fēng)險