天天看點

分布式系統全局唯一ID簡介、特點、生成

一、什麼是分布式系統唯一ID

在複雜分布式系統中,往往需要對大量的資料和消息進行唯一辨別。

如在金融、電商、支付、等産品的系統中,資料日漸增長,對資料分庫分表後需要有一個唯一ID來辨別一條資料或消息,資料庫的自增ID顯然不能滿足需求,此時一個能夠生成全局唯一ID的系統是非常必要的。

二、分布式系統唯一ID的特點

全局唯一性:不能出現重複的ID号,既然是唯一辨別,這是最基本的要求。

趨勢遞增:在MySQL InnoDB引擎中使用的是聚集索引,由于多數RDBMS使用B-tree的資料結構來存儲索引資料,在主鍵的選擇上面我們應該盡量使用有序的主鍵保證寫入性能。

單調遞增:保證下一個ID一定大于上一個ID,例如事務版本号、IM增量消息、排序等特殊需求。

資訊安全:如果ID是連續的,惡意使用者的扒取工作就非常容易做了,直接按照順序下載下傳指定URL即可;如果是訂單号就更危險了,競對可以直接知道我們一天的單量。是以在一些應用場景下,會需要ID無規則、不規則。

同時除了對ID号碼自身的要求,業務還對ID号生成系統的可用性要求極高,想象一下,如果ID生成系統癱瘓,這就會帶來一場災難。

由此總結下一個ID生成系統應該做到如下幾點:

平均延遲和TP999延遲都要盡可能低;

可用性5個9;

高QPS。

三、分布式系統唯一ID的實作方案

1.UUID

UUID(Universally Unique Identifier)的标準型式包含32個16進制數字,以連字号分為五段,形式為8-4-4-4-12的36個字元,示例:550e8400-e29b-41d4-a716-446655440000,到目前為止業界一共有5種方式生成UUID,詳情見IETF釋出的UUID規範 A Universally Unique IDentifier (UUID) URN Namespace。

優點:

性能非常高:本地生成,沒有網絡消耗。

缺點:

不易于存儲:UUID太長,16位元組128位,通常以36長度的字元串表示,很多場景不适用。

資訊不安全:基于MAC位址生成UUID的算法可能會造成MAC位址洩露,這個漏洞曾被用于尋找梅麗莎病毒的制作者位置。

ID作為主鍵時在特定的環境會存在一些問題,比如做DB主鍵的場景下,UUID就非常不适用:

2.資料庫生成

以MySQL舉例,利用給字段設定auto_increment_increment和auto_increment_offset來保證ID自增,每次業務使用下列SQL讀寫MySQL得到ID号。

這種方案的優缺點如下:

優點:

非常簡單,利用現有資料庫系統的功能實作,成本小,有DBA專業維護。

ID号單調自增,可以實作一些對ID有特殊要求的業務。

缺點:

強依賴DB,當DB異常時整個系統不可用,屬于緻命問題。配置主從複制可以盡可能的增加可用性,但是資料一緻性在特殊情況下難以保證。主從切換時的不一緻可能會導緻重複發号。

ID發号性能瓶頸限制在單台MySQL的讀寫性能。

3.Redis生成ID

當使用資料庫來生成ID性能不夠要求的時候,我們可以嘗試使用Redis來生成ID。

這主要依賴于Redis是單線程的,是以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY來實作。

比較适合使用Redis來生成每天從0開始的流水号。比如訂單号=日期+當日自增長号。可以每天在Redis中生成一個Key,使用INCR進行累加。

優點:

1)不依賴于資料庫,靈活友善,且性能優于資料庫。

2)數字ID天然排序,對分頁或者需要排序的結果很有幫助。

缺點:

1)如果系統中沒有Redis,還需要引入新的元件,增加系統複雜度。

2)需要編碼和配置的工作量比較大。

4.利用zookeeper生成唯一ID

zookeeper主要通過其znode資料版本來生成序列号,可以生成32位和64位的資料版本号,用戶端可以使用這個版本号來作為唯一的序列号。

很少會使用zookeeper來生成唯一ID。主要是由于需要依賴zookeeper,并且是多步調用API,如果在競争較大的情況下,需要考慮使用分布式鎖。是以,性能在高并發的分布式環境下,也不甚理想。

5.snowflake(雪花算法)方案

這種方案大緻來說是一種以劃分命名空間(UUID也算,由于比較常見,是以單獨分析)來生成ID的一種算法,這種方案把64-bit分别劃分成多段,分開來标示機器、時間等,比如在snowflake中的64-bit分别表示如下圖(圖檔來自網絡)所示:

41-bit的時間可以表示(1L<<41)/(1000L360024*365)=69年的時間,10-bit機器可以分别表示1024台機器。如果我們對IDC劃分有需求,還可以将10-bit分5-bit給IDC,分5-bit給工作機器。這樣就可以表示32個IDC,每個IDC下可以有32台機器,可以根據自身需求定義。12個自增序列号可以表示2^12個ID,理論上snowflake方案的QPS約為409.6w/s,這種配置設定方式可以保證在任何一個IDC的任何一台機器在任意毫秒内生成的ID都是不同的。

這種方式的優缺點是:

優點:

毫秒數在高位,自增序列在低位,整個ID都是趨勢遞增的。

不依賴資料庫等第三方系統,以服務的方式部署,穩定性更高,生成ID的性能也是非常高的。

可以根據自身業務特性配置設定bit位,非常靈活。

缺點:

強依賴機器時鐘,如果機器上時鐘回撥,會導緻發号重複或者服務會處于不可用狀态。

應用舉例Mongdb objectID

MongoDB官方文檔 ObjectID可以算作是和snowflake類似方法,通過“時間+機器碼+pid+inc”共12個位元組,通過4+3+2+3的方式最終辨別成一個24長度的十六進制字元

繼續閱讀