你不得不知的幾個互聯網ID生成器方案

服務化、分散式已成為當下系統開發的首選,高並發操作在數據存儲時,需要一套id生成器服務,來保證分散式情況下全局唯一性,以確保系統的訂單創建、交易支付等場景下數據的唯一性,否則將造成不可估量的損失。

基於時間戳

比如流水號規則如下:XX-YYYYMMDD-N位隨機數,這也是企業級應用開發常用的規則。此流水號對人比較友好,可識別性高,但容量受後面隨機數的限制,且數據量越大,生成時難度越高。前三部分每天的流水號基本固定,後面的N位隨機數生成後,需要校驗此前不存在,可依賴redis的set機制,每天的隨機數都寫到一個set集合中[set容易達42億之多,完全夠用],重新生成後要與set集合作比對,以確保其唯一性。一天內不重複,再結合確定日期來保證其唯一性。

N位隨機數生成時,可基於系統時間戳,再與一個大數取模生成。

UUID/GUID

最簡單直接暴力的方式,雖然能夠保證ID的唯一性,但是,它無法滿足業務系統需要的很多其他特性,例如:時間粗略有序性,可反解和可製造型。另外,UUID產生的時候使用完全的時間數據,性能比較差,並且UUID比較長,佔用空間大,間接導致資料庫性能下降,更重要的是,UUID並不具有有序性。系統容量較小的時候可以採用,變大後不建議採用此方式。

Vesta

GitHub 地址:github.com/robertleepea

Vesta是一款通用的ID產生器,互聯網俗稱統一發號器,它具有全局唯一、粗略有序、可反解和可製造等特性,它支持三種發布模式:嵌入發布模式、中心伺服器發布模式、REST發布模式,根據業務的性能需求,它可以產生最大峰值型和最小粒度型兩種類型的ID,它的實現架構使其具有高性能,高可用和可伸縮等互聯網產品需要的質量屬性,是一款通用的高性能的發號器產品。 提供4種應用部署方式,具體使用依場景而定:

  • REST發布模式(Netty)
  • REST發布模式(Tomcat)
  • 中心伺服器發布模式
  • 嵌入式發布模式

Twitter-Snowflake

GitHub 地址:github.com/twitter/snow

Twitter-Snowflake演算法產生的背景相當簡單,為了滿足Twitter每秒上萬條消息的請求,每條消息都必須分配一條唯一的id,這些id還需要一些大致的順序(方便客戶端排序),並且在分散式系統中不同機器產生的id必須不同。

snowflake的結構如下(用-分開):

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000

第一位為未使用,接下來的41位為毫秒級時間(41位的長度可以使用69年),然後是5位datacenterId和5位workerId(10位的長度最多支持部署1024個節點) ,最後12位是毫秒內的計數(12位的計數順序號支持每個節點每毫秒產生4096個ID序號)

一共加起來剛好64位,為一個Long型。(轉換成字元串長度為18)

snowflake生成的ID整體上按照時間自增排序,並且整個分散式系統內不會產生ID碰撞(由datacenter和workerId作區分),並且效率較高。據說:snowflake每秒能夠產生26萬個ID。

基於redis的分散式ID生成器

GitHub 地址:github.com/hengyunabc/r

依賴redis的EVAL,EVALSHA兩個命令,利用redis的lua腳本執行功能,在每個節點上通過lua腳本生成唯一ID。 生成的ID是64位的:

  • 使用41 bit來存放時間,精確到毫秒,可以使用41年。
  • 使用12 bit來存放邏輯分片ID,最大分片ID是4095
  • 使用10 bit來存放自增長ID,意味著每個節點,每毫秒最多可以生成1024個ID

Redis提供了TIME命令,可以取得redis伺服器上的秒數和微秒數。因些lua腳本返回的是一個四元組。

second, microSecond, partition, seq

客戶端要自己處理,生成最終ID。

((second * 1000 + microSecond / 1000) << (12 + 10)) + (shardId << 10) + seq;

在redis-id-generator-java目錄下,有example和benchmark代碼,提供了 Java客戶端生成模式,其它語言只要支持redis evalsha命令就可以了。

MongoDB的ObjectId

Mongodb集合中的每個document中都必須有一個"_id"鍵,這個鍵的值可以是任何類型的,在默認的情況下是個Objectid對象。mongodb的ObejctId生產思想在很多方面挺值得我們借鑒的,特別是在大型分散式的開發,如何構建輕量級的生產,如何將生產的負載進行轉移,如何以空間換取時間提高生產的最大優化等等。

網上有篇文章分析的還可以推薦給大家blogjava.net/dongbule/a

  • Spring Boot + Elasticsearch 實現大批量數據集下中文的精確匹配
  • Spring Boot + Elasticsearch 實現索引批量寫入
  • Spring Boot + Elasticsearch 實現索引的日常維護
  • 野蠻生長的前端,從雜牌軍到正規軍
  • 微服務體系下如何快速構建一個服務
  • 介紹幾款常用的在線API管理工具
  • 你不得不知的幾個互聯網ID生成器方案
  • 基於SpringCloud的Microservices架構實戰案例-序篇
  • 程序員,保護你的好奇心和求知慾

推薦閱讀:

2017就要結束了,再學點什麼呢?
優秀的項目管理與糟糕的項目管理
突破舊思維
人生已經過了 29565 天,敲代碼還來得及嗎?
Make it run, make it right, make it fast

TAG:互联网 | 软件开发 | Web开发 |