分布式唯一 ID

在分布式系統(tǒng)中,有些場景需要使用全局唯一 ID,一來作為業(yè)務(wù)標(biāo)識(shí),一來為了滿足接口的冪等性設(shè)計(jì)。例如我們文件系統(tǒng)中的 fid。
單表情況下我們可以直接使用數(shù)據(jù)庫的自增id,但是分庫分表后就無法滿足需求了,需要想辦法通過其他手段來實(shí)現(xiàn)。
對(duì)于全局唯一ID,需要具備的特性:

  • 全局唯一
  • 遞增
  • 高可用
  • 自主性
  • 安全性(不會(huì)暴露)

利用數(shù)據(jù)庫自增id生成

實(shí)現(xiàn)方式

image.png
  • 利用 MySQL 數(shù)據(jù)庫自增 id 的特性獲取到一個(gè) sequence
  • 上層服務(wù)(多臺(tái)機(jī)器)獲取到 sequence,然后在此基礎(chǔ)上逐步累加 step。相當(dāng)于每次獲取到的 sequence 共有 step 個(gè)id可用
  • 獲取到的 id 用盡后,重新獲取 sequence

優(yōu)點(diǎn)

  • 天然有序
  • 理解起來容易,實(shí)現(xiàn)起來簡單

缺點(diǎn)

  • “下發(fā) sequence 的服務(wù)” 以及 “數(shù)據(jù)庫” 是單點(diǎn)(使用多個(gè)水平庫來生成 sequence,自增id設(shè)置不同的初始值以及步長)
  • 數(shù)據(jù)庫遷移,需要提前預(yù)留出足夠的 sequence,防止沖突
  • 服務(wù)器重啟、單點(diǎn)故障會(huì)導(dǎo)致 id 不連續(xù)
  • 暴露一天的數(shù)據(jù)量

UUID

實(shí)現(xiàn)方式

優(yōu)點(diǎn)

  • 無需依賴中間件或三方服務(wù),可自主生成
  • 高并發(fā)
  • 各個(gè)語言均有實(shí)現(xiàn)庫可直接使用

缺點(diǎn)

  • 字符串存儲(chǔ),占空間,DB查詢及索引效率差
  • 不是自增id,可讀性差
  • 不同的實(shí)現(xiàn)方式可能泄漏信息

Redis/MongoDB 文檔全局唯一ID/zookeeper

實(shí)現(xiàn)方式

  • Redis
    利用 redis 單線程的特性,使用 incr 或 increby 生成 id

  • MongoDB 的 objectId
    3.2 及之前版本

    image.png

    3.2 之后版本
    image.png

  • zookeeper 數(shù)據(jù)節(jié)點(diǎn)的版本

優(yōu)點(diǎn)

  • 性能相較于數(shù)據(jù)庫會(huì)好上很多
  • 可以集群部署
  • 生成的id 可以帶上時(shí)間信息

缺點(diǎn)

  • 需要引入中間件,增加系統(tǒng)復(fù)雜度
  • 下發(fā) id 的服務(wù)同樣是一個(gè)單點(diǎn)

雪花算法

實(shí)現(xiàn)方式

image.png
  • 41bits 作為毫秒數(shù)。大概可以用 69.7 年
  • 10bits 作為機(jī)器編號(hào)(5bits 是數(shù)據(jù)中心,5bits 的機(jī)器 ID),支持 1024 個(gè)實(shí)例
  • 12bits 作為毫秒內(nèi)的序列號(hào)。一毫秒可以生成 4096 個(gè)序號(hào)

優(yōu)點(diǎn)

  • 本地生成,沒有網(wǎng)絡(luò)消耗,不需要引入中間件
  • 高并發(fā)
  • 包含時(shí)間信息

缺點(diǎn)

  • 依賴于機(jī)器時(shí)鐘,同一臺(tái)機(jī)器如果把時(shí)間回?fù)?,生成?ID 就會(huì)有重復(fù)的風(fēng)險(xiǎn)
    解決方案:
    • 將ID生成交給少量服務(wù)器,并關(guān)閉時(shí)鐘同步。
    • 直接報(bào)錯(cuò),交給上層業(yè)務(wù)處理。
    • 如果回?fù)軙r(shí)間較短,在耗時(shí)要求內(nèi),比如5ms,那么等待回?fù)軙r(shí)長后再進(jìn)行生成。
    • 如果回?fù)軙r(shí)間很長,那么無法等待,可以勻出少量位(1~2位)作為回?fù)芪唬坏r(shí)鐘回?fù)?,將回?fù)芪患?,可得到不一樣的ID,2位回?fù)芪辉试S標(biāo)記三次時(shí)鐘回?fù)?,基本夠使用。如果超出了,可以再選擇拋出異常。

可以看到我們采用的方案并沒有滿足全部全局ID的特性,就好像分布式系統(tǒng)的 CAP 特性,我們只能盡量多的滿足其中的特性。

沒有最好的方案,只有最合適的方案。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 作者:猿碼之家鏈接:http://www.itdecent.cn/p/4ba1c5e8c185來源:簡書著作權(quán)歸...
    小馬過河R閱讀 939評(píng)論 11 4
  • 在業(yè)務(wù)開發(fā)中,大量場景需要唯一ID來進(jìn)行標(biāo)識(shí):用戶需要唯一身份標(biāo)識(shí)、商品需要唯一標(biāo)識(shí)、消息需要唯一標(biāo)識(shí)、事件需要唯...
    稻哥說編程閱讀 16,387評(píng)論 1 5
  • 一,題記 所有的業(yè)務(wù)系統(tǒng),都有生成ID的需求,如訂單id,商品id,文章ID等。這個(gè)ID會(huì)是數(shù)據(jù)庫中的唯一主鍵,在...
    架構(gòu)師小秘圈閱讀 4,139評(píng)論 1 18
  • 設(shè)計(jì)目的: 在分布式條件下,生成唯一ID,速度快 要求: 長度8字節(jié),首位不能使用,故只能使用63bits 全局唯...
    蕭然AND沐橦閱讀 990評(píng)論 0 0
  • 前言 在互聯(lián)網(wǎng)的業(yè)務(wù)系統(tǒng)中,涉及到各種各樣的ID,如在支付系統(tǒng)中就會(huì)有支付ID、退款I(lǐng)D等。那一般生成ID都有哪些...
    Java大生閱讀 3,350評(píng)論 0 4

友情鏈接更多精彩內(nèi)容