SpringBoot集成全局唯⼀ID⽣成器UidGenerator
流⽔号⽣成器(全局唯⼀ ID⽣成器)是服务化系统的基础设施,其在保障系统的正确运⾏和⾼可⽤⽅⾯发挥着重要作⽤。⽽关于流⽔号⽣成算法⾸屈⼀指的当属 Snowflake雪花算法,然⽽ Snowflake本⾝很难在现实项⽬中直接使⽤,因此实际应⽤时需要⼀种可落地的⽅案。
Snowflake仓库
github/twitter/snowflake
UidGenerator 由百度⽤Java语⾔开发的, 基于 Snowflake算法的唯⼀ID⽣成器。UidGenerator以组件形式⼯作在应⽤项⽬中, ⽀持⾃定义workerId位数和初始化策略, 从⽽适⽤于docker等虚拟化环境下实例⾃动重启、漂移等场景。
UidGenerator仓库
github/baidu/uid-generator
UidGenerator中⽂⽂档
github/baidu/uid-generator/blob/master/README.zh_cn.md
0x01:先在 l中添加相关依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId&batis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>springboot推荐算法
<!--for Mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>8.0.12</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.9</version>
</dependency>
<!--必须放在最后-->
<dependency>
<groupId&desheep</groupId>
<groupId&desheep</groupId>
<artifactId>uid-generator</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
0x02: application.properties配置⽂件中添加配置(主要是 MySQL和 MyBatis配置)
server.port=9999
spring.datasource.url=jdbc:mysql://x:3306/xxx?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root
spring.datasource.password=xxx
spring.datasource.sql.jdbc.Driver
mybatis.mapper-locations=classpath:mapper/*.xml
0x03:创建数据库表
运⾏sql脚本以导⼊表WORKER_NODE, 脚本如下
DROP DATABASE IF EXISTS `xxxx`;
CREATE DATABASE `xxxx` ;
use `xxxx`;
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;
0x04:Spring配置
提供了两种⽣成器: DefaultUidGenerator、CachedUidGenerator。如对UID⽣成性能有要求, 请使⽤CachedUidGenerator
对应Spring配置分别为: l、l
DefaultUidGenerator配置
<!-- DefaultUidGenerator -->
<bean id="defaultUidGenerator" class="com.baidu.fsg.uid.impl.DefaultUidGenerator" lazy-init="false">
<property name="workerIdAssigner" ref="disposableWorkerIdAssigner"/>
<!-- Specified bits & epoch as your demand. No specified the default value will be used -->
<property name="timeBits" value="29"/>
<property name="workerBits" value="21"/>
<property name="seqBits" value="13"/>
<property name="epochStr" value="2016-09-20"/>
</bean>
<!-- ⽤完即弃的WorkerIdAssigner,依赖DB操作 -->
<bean id="disposableWorkerIdAssigner" class="com.baidu.fsg.uid.worker.DisposableWorkerIdAssigner" /> CachedUidGenerator配置
<!-- CachedUidGenerator -->
<bean id="cachedUidGenerator" class="com.baidu.fsg.uid.impl.CachedUidGenerator">
<property name="workerIdAssigner" ref="disposableWorkerIdAssigner" />
<!-- 以下为可选配置, 如未指定将采⽤默认值 -->
<!-- Specified bits & epoch as your demand. No specified the default value will be used -->
<property name="timeBits" value="29"/>
<property name="workerBits" value="21"/>
<property name="seqBits" value="13"/>
<property name="epochStr" value="2016-09-20"/>
<!-- RingBuffer size扩容参数, 可提⾼UID⽣成的吞吐量. -->
<!-- 默认:3, 原bufferSize=8192, 扩容后bufferSize= 8192 << 3 = 65536 -->
<property name="boostPower" value="3"></property>
<!-- 指定何时向RingBuffer中填充UID, 取值为百分⽐(0, 100), 默认为50 -->
<!-- 举例: bufferSize=1024, paddingFactor=50 -> threshold=1024 * 50 / 100 = 512. -->
<!-- 当环上可⽤UID数量 < 512时, 将⾃动对RingBuffer进⾏填充补全 -->
<property name="paddingFactor" value="50"></property>
<!-- 另外⼀种RingBuffer填充时机, 在Schedule线程中, 周期性检查填充 -->
<!-- 默认:不配置此项, 即不实⽤Schedule线程. 如需使⽤, 请指定Schedule线程时间间隔, 单位:秒 -->
<property name="scheduleInterval" value="60"></property>
<property name="scheduleInterval" value="60"></property>
<!-- 拒绝策略: 当环已满, ⽆法继续填充时 -->
<!-- 默认⽆需指定, 将丢弃Put操作, 仅⽇志记录. 如有特殊需求, 请实现RejectedPutBufferHandler接⼝(⽀持Lambda表达式) -->
<property name="rejectedPutBufferHandler" ref="XxxxYourPutRejectPolicy"></property>
<!-- 拒绝策略: 当环已空, ⽆法继续获取时 -->
<!-- 默认⽆需指定, 将记录⽇志, 并抛出UidGenerateException异常. 如有特殊需求, 请实现RejectedTakeBufferHandler接⼝(⽀持Lambda表达式) --> <property name="rejectedTakeBufferHandler" ref="XxxxYourTakeRejectPolicy"></property>
</bean>
<!-- ⽤完即弃的WorkerIdAssigner, 依赖DB操作 -->
<bean id="disposableWorkerIdAssigner" class="com.baidu.fsg.uid.worker.DisposableWorkerIdAssigner" />
Mybatis配置,l配置说明如下:
<!-- Spring annotation扫描 -->
<context:component-scan base-package="com.baidu.fsg.uid" />
<bean id="sqlSessionFactory" class="batis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:/META-INF/mybatis/mapper/M_WORKER*.xml" />
</bean>
<!-- 事务相关配置 -->
<tx:annotation-driven transaction-manager="transactionManager" order="1" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Mybatis Mapper扫描 -->
<bean class="batis.spring.mapper.MapperScannerConfigurer">
<property name="annotationClass" value="org.springframework.stereotype.Repository" />
<property name="basePackage" value="com.baidu.fsg.uid.worker.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<!-- 数据源配置 -->
<bean id="dataSource" parent="abstractDataSource">
<property name="driverClassName" value="${mysql.driver}" />
<property name="maxActive" value="${jdbc.maxActive}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="abstractDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="filters" value="${datasource.filters}" />
<property name="defaultAutoCommit" value="${datasource.defaultAutoCommit}" />
<property name="initialSize" value="${datasource.initialSize}" />
<property name="minIdle" value="${datasource.minIdle}" />
<property name="maxWait" value="${datasource.maxWait}" />
<property name="testWhileIdle" value="${stWhileIdle}" />
<property name="testOnBorrow" value="${stOnBorrow}" />
<property name="testOnReturn" value="${stOnReturn}" />
<property name="validationQuery" value="${datasource.validationQuery}" />
<property name="timeBetweenEvictionRunsMillis" value="${datasource.timeBetweenEvictionRunsMillis}" />
<property name="minEvictableIdleTimeMillis" value="${datasource.minEvictableIdleTimeMillis}" />
<property name="logAbandoned" value="${datasource.logAbandoned}" />
<property name="removeAbandoned" value="${veAbandoned}" />
<property name="removeAbandonedTimeout" value="${veAbandonedTimeout}" />
</bean>
<bean id="batchSqlSession" class="batis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
<constructor-arg index="1" value="BATCH" />
</bean>
0x05:测试
@Resource
private UidGenerator uidGenerator;
@Test
public void testSerialGenerate() {
// Generate UID
long uid = UID();
// Parse UID into [Timestamp, WorkerId, Sequence]
// {"UID":"180363646902239241","parsed":{ "timestamp":"2017-01-19 12:15:46", "workerId":"4", "sequence":"9" }}
System.out.println(uidGenerator.parseUID(uid));

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。