日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何设计一个分布式ID生成器

發(fā)布時(shí)間:2024/1/1 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何设计一个分布式ID生成器 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

應(yīng)用場景(Scenario)

現(xiàn)實(shí)中很多業(yè)務(wù)都有生成唯一ID的需求,例如:

  • 用戶ID
  • 微博ID
  • 聊天消息ID
  • 帖子ID
  • 訂單ID

需求(Needs)

這個ID往往會作為數(shù)據(jù)庫主鍵,所以需要保證全局唯一。數(shù)據(jù)庫會在這個字段上建立聚集索引(Clustered Index,參考 MySQL InnoDB),即該字段會影響各條數(shù)據(jù)再物理存儲上的順序。

ID還要盡可能,節(jié)省內(nèi)存,讓數(shù)據(jù)庫索引效率更高。基本上64位整數(shù)能夠滿足絕大多數(shù)的場景,但是如果能做到比64位更短那就更好了。需要根據(jù)具體業(yè)務(wù)進(jìn)行分析,預(yù)估出ID的最大值,這個最大值通常比64位整數(shù)的上限小很多,于是我們可以用更少的bit表示這個ID。

查詢的時(shí)候,往往有分頁或者排序的需求,所以需要給每條數(shù)據(jù)添加一個時(shí)間字段,并在其上建立普通索引(Secondary Index)。但是普通索引的訪問效率比聚集索引慢,如果能夠讓ID按照時(shí)間粗略有序,則可以省去這個時(shí)間字段。為什么不是按照時(shí)間精確有序呢?因?yàn)榘凑諘r(shí)間精確有序是做不到的,除非用一個單機(jī)算法,在分布式場景下做到精確有序性能一般很差。

這就引出了ID生成的三大核心需求:

  • 全局唯一(unique)
  • 按照時(shí)間粗略有序(sortable by time)
  • 盡可能短

下面介紹一些常用的生成ID的方法。

UUID

用過MongoDB的人會知道,MongoDB會自動給每一條數(shù)據(jù)賦予一個唯一的ObjectId,保證不會重復(fù),這是怎么做到的呢?實(shí)際上它用的是一種UUID算法,生成的ObjectId占12個字節(jié),由以下幾個部分組成,

  • 4個字節(jié)表示的Unix timestamp,
  • 3個字節(jié)表示的機(jī)器的ID
  • 2個字節(jié)表示的進(jìn)程ID
  • 3個字節(jié)表示的計(jì)數(shù)器

UUID是一類算法的統(tǒng)稱,具體有不同的實(shí)現(xiàn)。UUID的有點(diǎn)是每臺機(jī)器可以獨(dú)立產(chǎn)生ID,理論上保證不會重復(fù),所以天然是分布式的,缺點(diǎn)是生成的ID太長,不僅占用內(nèi)存,而且索引查詢效率低。

多臺MySQL服務(wù)器

既然MySQL可以產(chǎn)生自增ID,那么用多臺MySQL服務(wù)器,能否組成一個高性能的分布式發(fā)號器呢? 顯然可以。

假設(shè)用8臺MySQL服務(wù)器協(xié)同工作,第一臺MySQL初始值是1,每次自增8,第二臺MySQL初始值是2,每次自增8,依次類推。前面用一個 round-robin load balancer 擋著,每來一個請求,由 round-robin balancer 隨機(jī)地將請求發(fā)給8臺MySQL中的任意一個,然后返回一個ID。

Flickr就是這么做的,僅僅使用了兩臺MySQL服務(wù)器。可見這個方法雖然簡單無腦,但是性能足夠好。不過要注意,在MySQL中,不需要把所有ID都存下來,每臺機(jī)器只需要存一個MAX_ID就可以了。這需要用到MySQL的一個REPLACE INTO特性。

這個方法跟單臺數(shù)據(jù)庫比,缺點(diǎn)是ID是不是嚴(yán)格遞增的,只是粗略遞增的。不過這個問題不大,我們的目標(biāo)是粗略有序,不需要嚴(yán)格遞增。

Twitter Snowflake

比如 Twitter 有個成熟的開源項(xiàng)目,就是專門生成ID的,Twitter Snowflake?。Snowflake的核心算法如下:

最高位不用,永遠(yuǎn)為0,其余三組bit占位均可浮動,看具體的業(yè)務(wù)需求而定。默認(rèn)情況下41bit的時(shí)間戳可以支持該算法使用到2082年,10bit的工作機(jī)器id可以支持1023臺機(jī)器,序列號支持1毫秒產(chǎn)生4095個自增序列id。

Instagram用了類似的方案,41位表示時(shí)間戳,13位表示shard Id(一個shard Id對應(yīng)一臺PostgreSQL機(jī)器),最低10位表示自增ID,怎么樣,跟Snowflake的設(shè)計(jì)非常類似吧。這個方案用一個PostgreSQL集群代替了Twitter Snowflake 集群,優(yōu)點(diǎn)是利用了現(xiàn)成的PostgreSQL,容易懂,維護(hù)方便。

有的面試官會問,如何讓ID可以粗略的按照時(shí)間排序?上面的這種格式的ID,含有時(shí)間戳,且在高位,恰好滿足要求。如果面試官又問,如何保證ID嚴(yán)格有序呢?在分布式這個場景下,是做不到的,要想高性能,只能做到粗略有序,無法保證嚴(yán)格有序。

總結(jié)

以上是生活随笔為你收集整理的如何设计一个分布式ID生成器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。