您现在的位置是:亿华云 > 数据库
Springboot整合百度开源分布式ID生成器UIDGenerator
亿华云2025-10-09 06:57:59【数据库】6人已围观
简介环境:sprinboot2.3.12.RELEASE + uid-generator1.0.0简介UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器。UidGene
环境:sprinboot2.3.12.RELEASE + uid-generator1.0.0
简介
UidGenerator是整合Java实现的, 基于Snowflake算法的唯一ID生成器。UidGenerator以组件形式工作在应用项目中,百度 支持自定义workerId位数和初始化策略, 从而适用于docker等虚拟化环境下实例自动重启、漂移等场景。开源 在实现上,分布 UidGenerator通过借用未来时间来解决sequence天然存在的并发限制; 采用RingBuffer来缓存已生成的UID, 并行化UID的生产和消费, 同时对CacheLine补齐,避免了由RingBuffer带来的式ID生硬件级「伪共享」问题. 最终单机QPS可达600万。
依赖版本:Java8及以上版本,成器 MySQL(内置WorkerID分配器, 启动阶段通过DB进行分配; 如自定义实现, 则DB非必选依赖)
Snowflake算法

Snowflake算法描述:指定机器 & 同一时刻 & 某一并发序列,是整合唯一的。据此可生成一个64 bits的百度唯一ID(long)。默认采用上图字节分配方式:
sign(1bit) 固定1bit符号标识,开源即生成的分布UID为正数。 delta seconds (28 bits) 当前时间,式ID生相对于时间基点"2016-05-20"的成器增量值,单位:秒,整合最多可支持约8.7年 worker id (22 bits) 机器id,百度最多可支持约420w次机器启动。开源内置实现为在启动时由数据库分配,默认分配策略为用后即弃,后续可提供复用策略。 sequence (13 bits) 每秒下的并发序列,13 bits可支持每秒8192个并发。以上参数均可通过Spring进行自定义
CachedUidGenerator
RingBuffer环形数组,亿华云数组每个元素成为一个slot。RingBuffer容量,默认为Snowflake算法中sequence最大值,且为2^N。可通过boostPower配置进行扩容,以提高RingBuffer 读写吞吐量。
Tail指针、Cursor指针用于环形数组上读写slot:
Tail指针 表示Producer生产的最大序号(此序号从0开始,持续递增)。Tail不能超过Cursor,即生产者不能覆盖未消费的slot。当Tail已赶上curosr,此时可通过rejectedPutBufferHandler指定PutRejectPolicy Cursor指针 表示Consumer消费到的最小序号(序号序列与Producer序列相同)。Cursor不能超过Tail,即不能消费未生产的slot。当Cursor已赶上tail,此时可通过rejectedTakeBufferHandler指定TakeRejectPolicy
CachedUidGenerator采用了双RingBuffer,Uid-RingBuffer用于存储Uid、Flag-RingBuffer用于存储Uid状态(是否可填充、是否可消费)
由于数组元素在内存中是连续分配的,可最大程度利用CPU cache以提升性能。但同时会带来「伪共享」FalseSharing问题,为此在Tail、Cursor指针、Flag-RingBuffer中采用了CacheLine 补齐方式。云南idc服务商

RingBuffer填充时机
初始化预填充 RingBuffer初始化时,预先填充满整个RingBuffer. 即时填充 Take消费时,即时检查剩余可用slot量(tail - cursor),如小于设定阈值,则补全空闲slots。阈值可通过paddingFactor来进行配置,请参考Quick Start中CachedUidGenerator配置 周期填充 通过Schedule线程,定时补全空闲slots。可通过scheduleInterval配置,以应用定时填充功能,并指定Schedule时间间隔以上为百度的官方介绍,接下来我们将其整合到Springboot项目中
UIDGenerator下载
在下面地址下载uid-generator

UIDGenerator环境配置
创建表
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相关的配置。
项目配置
依赖
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency>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: falsemapper文件中的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()) ; } }

完毕!!!
很赞哦!(66123)