你不得不知的幾個互聯網ID生成器方案
服務化、分散式已成為當下系統開發的首選,高並發操作在數據存儲時,需要一套id生成器服務,來保證分散式情況下全局唯一性,以確保系統的訂單創建、交易支付等場景下數據的唯一性,否則將造成不可估量的損失。
基於時間戳
比如流水號規則如下:XX-YYYYMMDD-N位隨機數,這也是企業級應用開發常用的規則。此流水號對人比較友好,可識別性高,但容量受後面隨機數的限制,且數據量越大,生成時難度越高。前三部分每天的流水號基本固定,後面的N位隨機數生成後,需要校驗此前不存在,可依賴redis的set機制,每天的隨機數都寫到一個set集合中[set容易達42億之多,完全夠用],重新生成後要與set集合作比對,以確保其唯一性。一天內不重複,再結合確定日期來保證其唯一性。
N位隨機數生成時,可基於系統時間戳,再與一個大數取模生成。
UUID/GUID
最簡單直接暴力的方式,雖然能夠保證ID的唯一性,但是,它無法滿足業務系統需要的很多其他特性,例如:時間粗略有序性,可反解和可製造型。另外,UUID產生的時候使用完全的時間數據,性能比較差,並且UUID比較長,佔用空間大,間接導致資料庫性能下降,更重要的是,UUID並不具有有序性。系統容量較小的時候可以採用,變大後不建議採用此方式。
Vesta
GitHub 地址:https://github.com/robertleepeak/vesta-id-generator
Vesta是一款通用的ID產生器,互聯網俗稱統一發號器,它具有全局唯一、粗略有序、可反解和可製造等特性,它支持三種發布模式:嵌入發布模式、中心伺服器發布模式、REST發布模式,根據業務的性能需求,它可以產生最大峰值型和最小粒度型兩種類型的ID,它的實現架構使其具有高性能,高可用和可伸縮等互聯網產品需要的質量屬性,是一款通用的高性能的發號器產品。 提供4種應用部署方式,具體使用依場景而定:
- REST發布模式(Netty)
- REST發布模式(Tomcat)
- 中心伺服器發布模式
- 嵌入式發布模式
Twitter-Snowflake
GitHub 地址:https://github.com/twitter/snowflake
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 地址:https://github.com/hengyunabc/redis-id-generator
依賴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生產思想在很多方面挺值得我們借鑒的,特別是在大型分散式的開發,如何構建輕量級的生產,如何將生產的負載進行轉移,如何以空間換取時間提高生產的最大優化等等。
網上有篇文章分析的還可以推薦給大家http://www.blogjava.net/dongbule/archive/2011/06/12/352138.html。
- Spring Boot + Elasticsearch 實現大批量數據集下中文的精確匹配
- Spring Boot + Elasticsearch 實現索引批量寫入
- Spring Boot + Elasticsearch 實現索引的日常維護
- 野蠻生長的前端,從雜牌軍到正規軍
- 微服務體系下如何快速構建一個服務
- 介紹幾款常用的在線API管理工具
- 你不得不知的幾個互聯網ID生成器方案
- 基於SpringCloud的Microservices架構實戰案例-序篇
- 程序員,保護你的好奇心和求知慾
推薦閱讀:
※2017就要結束了,再學點什麼呢?
※優秀的項目管理與糟糕的項目管理
※突破舊思維
※人生已經過了 29565 天,敲代碼還來得及嗎?
※Make it run, make it right, make it fast