<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          分布式 ID 生成方案

          共 5572字,需瀏覽 12分鐘

           ·

          2021-08-23 16:25


          -     前言    -


          不管我們是不是有身份的人,我們一定是有身份證的人,身份證上面的號(hào)碼就是我們的ID,理論上這個(gè)ID是全國(guó)唯一的,而且通過(guò)這個(gè)號(hào)碼,我們還可以得到一些個(gè)人信息,比如前兩位可以確定我們第一次申請(qǐng)身份證的時(shí)候所在的省份、接下來(lái)的四位可以確定我們所在的區(qū)縣,然后還可以知道我們出生的年月以及性別。

          在我們的計(jì)算機(jī)應(yīng)用中,也處處存在的ID, 比如訂單編號(hào)、商品ID、微博ID、微信消息ID、書(shū)的ISDN號(hào)、商品條碼等等。通過(guò)ID,可以迅速定位到對(duì)象實(shí)體、為對(duì)象之間建立關(guān)聯(lián)、跟蹤對(duì)象在不同服務(wù)之間的流轉(zhuǎn)等等。

          有的ID是無(wú)意義的唯一的標(biāo)識(shí),有的ID還能提供額外的信息,比如時(shí)間和機(jī)房信息等等。為了確保唯一性,有的ID使用很長(zhǎng)的字節(jié)數(shù),比如256個(gè)字節(jié),有的通過(guò)遞增的long類(lèi)型,只需要8個(gè)字節(jié)來(lái)表示。考慮到存儲(chǔ)、信息包含量、性能、安全等因素,一個(gè)好的ID的設(shè)計(jì)至關(guān)重要。

          介紹ID生成和分布式的方案的文章已經(jīng)非常非常多了,比如文末中的參考資料中的文章,所以我在本文中簡(jiǎn)潔的匯總各個(gè)方案的優(yōu)缺點(diǎn),然后介紹一個(gè)分布式的ID生成器項(xiàng)目rpcxio/did,它可以實(shí)現(xiàn)單節(jié)點(diǎn)百萬(wàn)級(jí)的ID生成。



          -     ID 生成方案    -


          UUID/GUID


          通用唯一識(shí)別碼(Universally Unique Identifier,縮寫(xiě):UUID)是用于計(jì)算機(jī)體系中以識(shí)別信息數(shù)目的一個(gè)128位標(biāo)識(shí)符,也就是可以通過(guò)16個(gè)字節(jié)來(lái)表示。

          UUID可以根據(jù)標(biāo)準(zhǔn)方法生成,不依賴中央機(jī)構(gòu)的注冊(cè)和分配,UUID具有唯一性,這與其他大多數(shù)編號(hào)方案不同。重復(fù)UUID碼概率接近零,可以忽略不計(jì)。

          GUID有時(shí)專(zhuān)指微軟對(duì)UUID標(biāo)準(zhǔn)的實(shí)現(xiàn)(Globally Unique Identifier, 縮寫(xiě):GUID),通常表示成32個(gè)16進(jìn)制數(shù)字(0-9,A-F)組成的字符串,如:{21EC2020-3AEA-1069-A2DD-08002B30309D},實(shí)質(zhì)上還是是一個(gè)128位長(zhǎng)的二進(jìn)制整數(shù),在Windows生態(tài)圈中常用。

          UUID 由開(kāi)放軟件基金會(huì)(OSF)標(biāo)準(zhǔn)化,作為分布式計(jì)算環(huán)境(DCE)的一部分。

          UUID的標(biāo)準(zhǔn)型式包含32個(gè)16進(jìn)位數(shù)字,以連字號(hào)分為五段,形式為8-4-4-4-12的32個(gè)字元。范例:550e8400-e29b-41d4-a716-446655440000

          在其規(guī)范的文本表示中,UUID 的 16 個(gè) 8 位字節(jié)表示為 32 個(gè)十六進(jìn)制(基數(shù)16)數(shù)字,顯示在由連字符分隔 '-' 的五個(gè)組中,"8-4-4-4-12" 總共 36 個(gè)字符(32 個(gè)字母數(shù)字字符和 4 個(gè)連字符)。例如:

          123e4567-e89b-12d3-a456-426655440000xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

          ?四位數(shù)字 M表示 UUID 版本,數(shù)字 N的一至三個(gè)最高有效位表示 UUID 變體。在例子中,M 是 1 而且 N 是 a(10xx),這意味著此 UUID 是 "變體1"、"版本1" UUID;即基于時(shí)間的 DCE/RFC 4122 UUID。

          對(duì)于 "變體(variants)1" 和 "變體2",標(biāo)準(zhǔn)中定義了五個(gè)"版本(versions)",并且在特定用例中每個(gè)版本可能比其他版本更合適。

          版本由 M 字符串中指示。

          • "版本1" UUID 是根據(jù)時(shí)間和節(jié)點(diǎn) ID(通常是MAC地址)生成;
          • "版本2" UUID是根據(jù)標(biāo)識(shí)符(通常是組或用戶ID)、時(shí)間和節(jié)點(diǎn)ID生成;
          • "版本3" 和 "版本5" 確定性UUID 通過(guò)散列 (hashing) 命名空間 (namespace) 標(biāo)識(shí)符和名稱(chēng)生成;
          • "版本4" UUID 使用隨機(jī)性或偽隨機(jī)性生成。

          更詳細(xì)的信息可以參考wikipedia和RFC文檔。

          • 優(yōu)點(diǎn)
            • 容易實(shí)現(xiàn),產(chǎn)生快
            • ID唯一(幾乎不會(huì)產(chǎn)生重復(fù)id)
            • 無(wú)需中心化的服務(wù)器
            • 不會(huì)泄漏商業(yè)機(jī)密
          • 缺點(diǎn)
            • 可讀性差
            • 占用空間太多(16個(gè)字節(jié))
            • 影響數(shù)據(jù)庫(kù)的性能, 比如UUID or GUID as Primary Keys? Be Careful!



          -     遞增的整數(shù)    -


          可以通過(guò)關(guān)系型數(shù)據(jù)庫(kù)的自增主鍵產(chǎn)生唯一的ID,現(xiàn)在流行的商業(yè)數(shù)據(jù)庫(kù)都支持自增主鍵的特性,比如mysql等。

          一些nosql數(shù)據(jù)庫(kù)也提供類(lèi)似特性,比如Redis。

          • 優(yōu)點(diǎn)
            • 容易產(chǎn)生
            • 可讀性好,容易記住
            • 存儲(chǔ)很小,比如4個(gè)字節(jié)
          • 缺點(diǎn)
            • 需要中心化的服務(wù)器,并且需要處理單點(diǎn)的問(wèn)題,而且單點(diǎn)有性能瓶頸的問(wèn)題。
            • 如果ID暴露給公共訪問(wèn),可能會(huì)泄漏商業(yè)機(jī)密。比如最近渾水報(bào)告通過(guò)統(tǒng)計(jì)銷(xiāo)售小票推斷出某商業(yè)模式的每日單量。
            • 需要訪問(wèn)一次數(shù)據(jù)庫(kù)獲取ID



          -     隨機(jī)數(shù)    -


          遞增的整數(shù)可以用在內(nèi)部的服務(wù)中,如果用在外部,可能會(huì)泄漏信息,所以如果能產(chǎn)生隨機(jī)數(shù)就可以解決這個(gè)問(wèn)題。

          當(dāng)然直接生成隨機(jī)數(shù)可能比較困難,你可以在遞增的整數(shù)上產(chǎn)生偽隨機(jī)的整數(shù),比如使用skip32, 它還可以直接進(jìn)行反解碼,在內(nèi)部反解出原來(lái)的遞增的ID,所以在一些場(chǎng)景的也有廣泛的應(yīng)用,比如在Postgrepsql中可以實(shí)現(xiàn)skip32 function)。
          另外一個(gè)比較常用的加密遞增ID方法是hashid,它可以轉(zhuǎn)換數(shù)字比如347為字符串yr8,并且還可以反解出來(lái),提供了很多語(yǔ)言的實(shí)現(xiàn),比如go-hashids、hashids-java、hashids.c等。

          對(duì)于64 bit的整數(shù),你可以使用Block ciphers實(shí)現(xiàn)加密。也有把64 bit整數(shù)分成兩部分,分別應(yīng)用skip32進(jìn)行加密的。

          • 優(yōu)點(diǎn)
            • 可讀性高
            • 占用存儲(chǔ)小,4個(gè)字節(jié)就可以了
            • 隨機(jī),不會(huì)泄漏信息
          • 缺點(diǎn)
            • 同樣需要中心化的服務(wù),有單點(diǎn)問(wèn)題和性能問(wèn)題
            • 需要兩步,先產(chǎn)生遞增的ID,再進(jìn)行隨機(jī)加密



          -     隨機(jī)字符串    -


          另外一個(gè)產(chǎn)生隨機(jī)ID方法是直接產(chǎn)生一個(gè)小的隨機(jī)的字符串,比如短網(wǎng)址服務(wù)中的ID。產(chǎn)生隨機(jī)字符串的方法很多, 比圖tinyurl和bit.ly使用的基于62字符的隨機(jī)字符串, 基于hash(MD5)+base62等, 應(yīng)用在Bitcoin地址上的可讀性更好的Base58。

          • 優(yōu)點(diǎn)
            • 短,5個(gè)字符(字節(jié))就可以表示10億個(gè)ID。
            • 可讀性高
            • 隨機(jī),不會(huì)泄漏信息
          • 缺點(diǎn)
            • ID可能不唯一,需要檢查和處理



          -     Twitter的snowflake算法    -


          Twitter的snowflake分布式ID的算法是目前廣泛使用的分布式ID算法,盡管有很多變種,比如位數(shù)的不同,時(shí)間片大小不同、node bit數(shù)放在最后等各種變種,但是主要思想還是來(lái)自于snowflake的思想。同時(shí)訪問(wèn)方法也各種個(gè)樣,比如提供memcached協(xié)議訪問(wèn)和Redis協(xié)議訪問(wèn)等等。

          Twitter在2010年兒童節(jié)的時(shí)候在官方博客上介紹了snowflake算法,內(nèi)部用來(lái)表示每一條tweet,盡管這個(gè)項(xiàng)目已經(jīng)不再維護(hù)了snowflake-2010。


          snowflake算法采用64bit存儲(chǔ)ID, 最高位備用,暫時(shí)不使用。接下來(lái)的41 bit做時(shí)間戳,最小時(shí)間單位為毫秒。再接下來(lái)的10 bit做機(jī)器ID(worker id),然后最后12 bit在單位時(shí)間(毫秒)遞增。

          41 bit表示時(shí)間戳大約可以使用69年(2^41 -1), 為了盡可能的表示時(shí)間,時(shí)間戳可以從第一次部署的時(shí)候開(kāi)始計(jì)算,比如2020-02-02 00:00:00, 這樣69年內(nèi)可以無(wú)虞。

          10 bit區(qū)分機(jī)器,所以可以支持1024臺(tái)機(jī)器。你也可以把10bit分成兩部分,一部分做數(shù)據(jù)中心的ID,一部分做機(jī)器的ID,比如55分的化,可以支持32個(gè)數(shù)據(jù)中心,每個(gè)數(shù)據(jù)中心最多可以支持32臺(tái)機(jī)器。

          12 bit自增值可以表示4096的ID,也就是說(shuō)每臺(tái)機(jī)器每以毫秒最多產(chǎn)生4096個(gè)ID,這是它的最大性能。

          正如前面所說(shuō),時(shí)間戳、機(jī)器ID、自增ID所占的位數(shù)可以根據(jù)你實(shí)際的情況做調(diào)整。

          snowflake還有一個(gè)很好的特性就是基本保持順序性,因?yàn)樗那皫孜皇菚r(shí)間戳,可以對(duì)ID按照時(shí)間進(jìn)行排序。另外在微服務(wù)中直接使用ID就可以計(jì)算sla。

          • 優(yōu)點(diǎn)
            • 存儲(chǔ)少, 8個(gè)字節(jié)
            • 可讀性高
            • 性能好,可以中心化的產(chǎn)生ID,也可以獨(dú)立節(jié)點(diǎn)生成
          • 缺點(diǎn)
            • 時(shí)間回?fù)軙?huì)重復(fù)產(chǎn)生ID
            • ID生成有規(guī)律性,信息容易泄漏



          -     MongoDB ObjectID    -


          MongoDB的主鍵類(lèi)型ObjectID也是一種ID生成方案,比如5349b4ddd2781d08c09890f3,它看起來(lái)是一個(gè)包含24個(gè)字符的字符串,實(shí)際采用12個(gè)字節(jié)來(lái)存儲(chǔ)。


          它使用4個(gè)字節(jié)代表時(shí)間戳,3個(gè)字節(jié)代表機(jī)器ID,2個(gè)字節(jié)代表機(jī)器進(jìn)程ID,然后3個(gè)字節(jié)代表自增值。

          相對(duì)于snowflake,它采用了更多的存儲(chǔ)(多了四個(gè)字節(jié)),可以容納更多的信息:
          • 優(yōu)點(diǎn)
            • 可讀性高
            • 性能好,可以中心化的產(chǎn)生ID,也可以獨(dú)立節(jié)點(diǎn)生成
          • 缺點(diǎn)
            • 占用存儲(chǔ)較多
            • 時(shí)間回?fù)軙?huì)重復(fù)產(chǎn)生ID
            • ID生成有規(guī)律性,信息容易泄漏



          -     分布式 ID 生成器服務(wù) did    -


          前面是一些ID生成的背景知識(shí)的介紹,這里介紹一個(gè)分布式ID生成器rpcxio/did),它基于snowflake的算法,但是提供了可以定制的算法,支持初始化設(shè)置worker id和自增值的bit數(shù)。

          因?yàn)樗且粋€(gè)中心化的ID生成器服務(wù),所以每次獲取ID都有額外的網(wǎng)絡(luò)開(kāi)銷(xiāo),所以最好一次申請(qǐng)一批數(shù)據(jù),然后client在本地使用,用不了丟掉即可,所以did服務(wù)還提供批量獲取ID的方法。

          安裝did的服務(wù)需要定時(shí)的和時(shí)間服務(wù)器進(jìn)行同步,這個(gè)短時(shí)間的回?fù)懿粫?huì)影響ID的產(chǎn)生。重啟服務(wù)一般也沒(méi)有問(wèn)題,因?yàn)楦鱾€(gè)節(jié)點(diǎn)和時(shí)間服務(wù)器的誤差在毫秒左右,而重啟至少是秒級(jí)的操作,所以不會(huì)有重復(fù)的ID產(chǎn)生。唯一怕的時(shí)候手工將時(shí)間回?fù)芤粋€(gè)很長(zhǎng)的時(shí)間(幾個(gè)小時(shí)、幾天),然后這個(gè)時(shí)候再重啟服務(wù),一般生產(chǎn)環(huán)境中也不會(huì)這么去做。

          因?yàn)榭梢圆渴鸲鄠€(gè)did服務(wù)做集群,所以可以提供容錯(cuò)機(jī)制,少量did節(jié)點(diǎn)宕機(jī)不會(huì)影響ID生成服務(wù)的訪問(wèn)。

          因?yàn)閟nowflake算法性能優(yōu)異,所以ID生成服務(wù)部署的節(jié)點(diǎn)不需要很多,每個(gè)機(jī)房只需要幾臺(tái)機(jī)器就可以了,所以你可以壓縮worker id占用的bit數(shù),擴(kuò)大自增值占用的bit數(shù)。

          測(cè)試中,單個(gè)節(jié)點(diǎn)可以提供12萬(wàn)ID/秒的產(chǎn)生速度,而如果采用批量獲取100ID的話,可以取得接近三百萬(wàn)ID/秒的性能。

          1256個(gè)client并發(fā),每次只獲取1個(gè)ID, ID的產(chǎn)生速度是 12萬(wàn)個(gè)ID/秒。./bclient -addr 192.168.15.225:8972 -n 100000total IDs: 25600000, duration: 3m31.581592489s, id/s: 1209932、如果采用批量獲取,盡量減少網(wǎng)絡(luò)消耗,256個(gè)client并發(fā),每次只獲取100個(gè)ID, ID的產(chǎn)生速度是 297萬(wàn)個(gè)ID/秒。./bclient -addr 192.168.15.225:8972 -n 1000000 -b 100total IDs: 256000000, duration: 1m26.178942509s, id/s: 2970563

          參考資料
          1. https://www.simpleorientedarchitecture.com/7-strategies-for-assigning-ids/
          2. https://www.callicoder.com/distributed-unique-id-sequence-number-generator/
          3. https://juejin.im/post/5b3a23746fb9a024e15cad79
          4. https://tech.meituan.com/2017/04/21/mt-leaf.html
          5. https://i6448038.github.io/2019/09/28/snowflake/
          6. https://soulmachine.gitbooks.io/system-design/content/cn/distributed-id-generator.html
          7. https://juejin.im/post/5bb0217ef265da0ac2567b42
          8. https://chai2010.cn/advanced-go-programming-book/ch6-cloud/ch6-01-dist-id.html
          9. https://zh.wikipedia.org/zh-hans/%E9%80%9A%E7%94%A8%E5%94%AF%E4%B8%80%E8%AF%86%E5%88%AB%E7%A0%81
          10. https://zhuanlan.zhihu.com/p/46404167


          者:smallnest

          來(lái)源:

          https://colobu.com/2020/02/21/ID-generator/

          瀏覽 58
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色1级片 | 亚洲乱码精品 | 日本特一级A片 | 2024中文字幕在线 | 婷婷成人娱乐网 |