在復雜分布式系統(tǒng)中,往往需要對大量的數據和消息進行唯一標識。
如在金融、電商、支付、等產品的系統(tǒng)中,數據日漸增長,對數據分庫分表后需要有一個唯一ID來標識一條數據或消息,數據庫的自增ID顯然不能滿足需求,此時一個能夠生成全局唯一ID的系統(tǒng)是非常必要的。
同時除了對ID號碼自身的要求,業(yè)務還對ID號生成系統(tǒng)的可用性要求極高,想象一下,如果ID生成系統(tǒng)癱瘓,這就會帶來一場災難。
由此總結下一個ID生成系統(tǒng)應該做到如下幾點:
1.UUID
UUID(Universally Unique Identifier)的標準型式包含32個16進制數字,以連字號分為五段,形式為8-4-4-4-12的36個字符,示例:550e8400-e29b-41d4-a716-446655440000,到目前為止業(yè)界一共有5種方式生成UUID,詳情見IETF發(fā)布的UUID規(guī)范 A Universally Unique IDentifier (UUID) URN Namespace。
優(yōu)點:
缺點:
2.數據庫生成
以MySQL舉例,利用給字段設置auto_increment_increment和auto_increment_offset來保證ID自增,每次業(yè)務使用下列SQL讀寫MySQL得到ID號。
這種方案的優(yōu)缺點如下:
優(yōu)點:
缺點:
3.Redis生成ID
當使用數據庫來生成ID性能不夠要求的時候,我們可以嘗試使用Redis來生成ID。
這主要依賴于Redis是單線程的,所以也可以用生成全局唯一的ID??梢杂肦edis的原子操作 INCR和INCRBY來實現。
比較適合使用Redis來生成每天從0開始的流水號。比如訂單號=日期+當日自增長號??梢悦刻煸赗edis中生成一個Key,使用INCR進行累加。
優(yōu)點:
1)不依賴于數據庫,靈活方便,且性能優(yōu)于數據庫。
2)數字ID天然排序,對分頁或者需要排序的結果很有幫助。
缺點:
1)如果系統(tǒng)中沒有Redis,還需要引入新的組件,增加系統(tǒng)復雜度。
2)需要編碼和配置的工作量比較大。
4.利用zookeeper生成唯一ID
zookeeper主要通過其znode數據版本來生成序列號,可以生成32位和64位的數據版本號,客戶端可以使用這個版本號來作為唯一的序列號。
很少會使用zookeeper來生成唯一ID。主要是由于需要依賴zookeeper,并且是多步調用API,如果在競爭較大的情況下,需要考慮使用分布式鎖。因此,性能在高并發(fā)的分布式環(huán)境下,也不甚理想。
5.snowflake(雪花算法)方案
這種方案大致來說是一種以劃分命名空間(UUID也算,由于比較常見,所以單獨分析)來生成ID的一種算法,這種方案把64-bit分別劃分成多段,分開來標示機器、時間等,比如在snowflake中的64-bit分別表示如下圖(圖片來自網絡)所示:
41-bit的時間可以表示(1L<41) 1000l*3600*24*365)="">41)>
這種方式的優(yōu)缺點是:
優(yōu)點:
缺點:
應用舉例Mongdb objectID
MongoDB官方文檔 ObjectID可以算作是和snowflake類似方法,通過“時間+機器碼+pid+inc”共12個字節(jié),通過4+3+2+3的方式最終標識成一個24長度的十六進制字符。