新聞中心
SpringBoot整合百度開源分布式ID生成器UIDGenerator
作者:FastCoder 2021-07-14 07:17:37
開發(fā)
前端
分布式 UidGenerator是Java實現(xiàn)的, 基于Snowflake算法的唯一ID生成器。UidGenerator以組件形式工作在應用項目中, 支持自定義workerId位數(shù)和初始化策略, 從而適用于docker等虛擬化環(huán)境下實例自動重啟、漂移等場景。

江川網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、APP開發(fā)、成都響應式網(wǎng)站建設公司等網(wǎng)站項目制作,到程序開發(fā),運營維護。創(chuàng)新互聯(lián)從2013年成立到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設就選創(chuàng)新互聯(lián)。
環(huán)境:sprinboot2.3.12.RELEASE + uid-generator1.0.0
簡介
UidGenerator是Java實現(xiàn)的, 基于Snowflake算法的唯一ID生成器。UidGenerator以組件形式工作在應用項目中, 支持自定義workerId位數(shù)和初始化策略, 從而適用于docker等虛擬化環(huán)境下實例自動重啟、漂移等場景。 在實現(xiàn)上, UidGenerator通過借用未來時間來解決sequence天然存在的并發(fā)限制; 采用RingBuffer來緩存已生成的UID, 并行化UID的生產(chǎn)和消費, 同時對CacheLine補齊,避免了由RingBuffer帶來的硬件級「偽共享」問題. 最終單機QPS可達600萬。
依賴版本:Java8及以上版本, MySQL(內置WorkerID分配器, 啟動階段通過DB進行分配; 如自定義實現(xiàn), 則DB非必選依賴)
Snowflake算法
Snowflake算法描述:指定機器 & 同一時刻 & 某一并發(fā)序列,是唯一的。據(jù)此可生成一個64 bits的唯一ID(long)。默認采用上圖字節(jié)分配方式:
- sign(1bit) 固定1bit符號標識,即生成的UID為正數(shù)。
- delta seconds (28 bits) 當前時間,相對于時間基點"2016-05-20"的增量值,單位:秒,最多可支持約8.7年
- worker id (22 bits) 機器id,最多可支持約420w次機器啟動。內置實現(xiàn)為在啟動時由數(shù)據(jù)庫分配,默認分配策略為用后即棄,后續(xù)可提供復用策略。
- sequence (13 bits) 每秒下的并發(fā)序列,13 bits可支持每秒8192個并發(fā)。
以上參數(shù)均可通過Spring進行自定義
CachedUidGenerator
RingBuffer環(huán)形數(shù)組,數(shù)組每個元素成為一個slot。RingBuffer容量,默認為Snowflake算法中sequence最大值,且為2^N。可通過boostPower配置進行擴容,以提高RingBuffer 讀寫吞吐量。
Tail指針、Cursor指針用于環(huán)形數(shù)組上讀寫slot:
- Tail指針 表示Producer生產(chǎn)的最大序號(此序號從0開始,持續(xù)遞增)。Tail不能超過Cursor,即生產(chǎn)者不能覆蓋未消費的slot。當Tail已趕上curosr,此時可通過rejectedPutBufferHandler指定PutRejectPolicy
- Cursor指針 表示Consumer消費到的最小序號(序號序列與Producer序列相同)。Cursor不能超過Tail,即不能消費未生產(chǎn)的slot。當Cursor已趕上tail,此時可通過rejectedTakeBufferHandler指定TakeRejectPolicy
CachedUidGenerator采用了雙RingBuffer,Uid-RingBuffer用于存儲Uid、Flag-RingBuffer用于存儲Uid狀態(tài)(是否可填充、是否可消費)
由于數(shù)組元素在內存中是連續(xù)分配的,可最大程度利用CPU cache以提升性能。但同時會帶來「偽共享」FalseSharing問題,為此在Tail、Cursor指針、Flag-RingBuffer中采用了CacheLine 補齊方式。
RingBuffer填充時機
- 初始化預填充 RingBuffer初始化時,預先填充滿整個RingBuffer.
- 即時填充 Take消費時,即時檢查剩余可用slot量(tail - cursor),如小于設定閾值,則補全空閑slots。閾值可通過paddingFactor來進行配置,請參考Quick Start中CachedUidGenerator配置
- 周期填充 通過Schedule線程,定時補全空閑slots??赏ㄟ^scheduleInterval配置,以應用定時填充功能,并指定Schedule時間間隔
以上為百度的官方介紹,接下來我們將其整合到Springboot項目中
UIDGenerator下載
在下面地址下載uid-generator
UIDGenerator環(huán)境配置
創(chuàng)建表
- DROP TABLE IF EXISTS WORKER_NODE;
- CREATE TABLE WORKER_NODE
- (
- ID BIGINT NOT NULL AUTO_INCREMENT COMMENT 'auto increment id',
- HOST_NAME VARCHAR(64) NOT NULL COMMENT 'host name',
- PORT VARCHAR(64) NOT NULL COMMENT 'port',
- TYPE INT NOT NULL COMMENT 'node type: ACTUAL or CONTAINER',
- LAUNCH_DATE DATE NOT NULL COMMENT 'launch date',
- MODIFIED TIMESTAMP NOT NULL COMMENT 'modified time',
- CREATED TIMESTAMP NOT NULL COMMENT 'created time',
- PRIMARY KEY(ID)
- )COMMENT='DB WorkerID Assigner for UID Generator',ENGINE = INNODB;
將其項目中的mapper.xml文件copy到自己項目中,對應的WorkerNodeEntity,WorkerNodeDAO,
DisposableWorkerIdAssigner都copy到自己的項目中。
DisposableWorkerIdAssigner主要是修改注入的dao,因為這里我們需要修改默認的dao相關的配置。
項目配置
依賴
mysql mysql-connector-java runtime org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.4 com.github.pagehelper pagehelper-spring-boot-starter 1.3.0
mybatis配置
- pagehelper:
- helperDialect: mysql
- reasonable: true
- pageSizeZero: true
- offsetAsPageNum: true
- rowBoundsWithCount: true
- ---
- mybatis:
- type-aliases-package: com.pack.domain
- mapper-locations:
- - classpath:/mappers/*.xml
- configuration:
- lazy-loading-enabled: false
- aggressive-lazy-loading: false
mapper文件中的namespace及對應domain修改為自己路徑下的。
配置UIDGenerator
- @Configuration
- public class UIDConfig {
- @Bean
- public DefaultUidGenerator defaultUidGenerator(DisposableWorkerIdAssigner disposableWorkerIdAssigner) {
- DefaultUidGenerator defaultUidGenerator = new DefaultUidGenerator() ;
- defaultUidGenerator.setWorkerIdAssigner(disposableWorkerIdAssigner) ;
- defaultUidGenerator.setTimeBits(29) ;
- defaultUidGenerator.setWorkerBits(21) ;
- defaultUidGenerator.setSeqBits(13) ;
- defaultUidGenerator.setEpochStr("2021-01-01") ;
- return defaultUidGenerator ;
- }
- }
注意這里的
DisposableWorkerIdAssigner是copy到自己項目中的,不是百度提供的。
- @Component
- public class DisposableWorkerIdAssigner implements WorkerIdAssigner {
- @Resource
- private WorkerNodeMapper workerNodeDAO;
- // other code
- }
到此所有的都配置完成了。
測試
- @Resource
- private DefaultUidGenerator uidGenerator ;
- @Test
- public void testGeneratorId() {
- for (int i = 0; i < 10; i++) {
- System.out.println(uidGenerator.getUID()) ;
- }
- }
完畢!!!
本文標題:Springboot整合百度開源分布式ID生成器UIDGenerator
標題來源:http://m.fisionsoft.com.cn/article/dpphgog.html


咨詢
建站咨詢
