概述
百度的ui-dgenerator也是根据snowflake算法更改的方法,关于snowflake算法不做介绍,不懂的可以百度。
snowflake算法有个缺点是:时间回拨问题,官方文档也是抛出异常。
分布式唯一id:snowflake算法思考文章地址: https://www.cnblogs.com/lirenzuo/p/8440413.html
分析时间回拨产生原因
第一:人物操作,在真实环境一般不会有那个傻逼干这种事情,所以基本可以排除。
第二:由于有些业务等需要,机器需要同步时间服务器(在这个过程中可能会存在时间回拨,查了下我们服务器一般在10ms以内(2小时同步一次))。
解决方法
由于是分布在各各机器自己上面,如果要几台集中的机器(并且不做时间同步),那么就基本上就不存在回拨可能性了(曲线救国也是救国,哈哈),但是也的确带来了新问题,各各结点需要访问集中机器,要保证性能,百度的uid-generator产生就是基于这种情况做的(每次取一批回来,很好的思想,性能也非常不错)
官方代码地址:https://github.com/baidu/uid-generator
本项目的地址: https://download.csdn.net/download/u014373554/11340492
spring boot 版本: 2.1.4.RELEASE
截图整个项目的图片
先引入pom文件:
<!-- 百度 uidgenerator 生成唯一的ID-->
<dependency>
<groupId>com.xfvape</groupId>
<artifactId>uid-generator</artifactId>
<version>0.0.1-RELEASE</version>
</dependency>
完整pom文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--这个是springcloud Alibaba 使用Nacos作为服务注册发现组件-->
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.9.0.RELEASE</version>
</dependency>-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 百度 uidgenerator 生成唯一的ID-->
<dependency>
<groupId>com.xfvape</groupId>
<artifactId>uid-generator</artifactId>
<version>0.0.1-RELEASE</version>
</dependency>
创建数据库存
导入官网数据库SQL https://github.com/baidu/uid-generator/blob/master/src/main/scripts/WORKER_NODE.sql
也就是一张表
我这里是在nacos库中,创建了这张表
CREATE TABLE `WORKER_NODE` (
`ID` bigint(20) 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(11) NOT NULL COMMENT 'node type: ACTUAL or CONTAINER',
`LAUNCH_DATE` date NOT NULL COMMENT 'launch date',
`MODIFIED` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'modified time',
`CREATED` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'created time',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COMMENT='DB WorkerID Assigner for UID Generator';
如果报错,基本上是时间问题,因为mysql 低版本控制比较严格,解决方法有多种方式
方式一:
直接把TIMESTAMP改成DATETIME 即可
方式二:
执行SQL 语句前先执行:
set sql_mode="NO_ENGINE_SUBSTITUTION";
新建 mapper:WORKER_NODE.xml
放在resources/mapper文件夹下面:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xfvape.uid.worker.dao.WorkerNodeDAO">
<resultMap id="workerNodeRes"
type="com.xfvape.uid.worker.entity.WorkerNodeEntity">
<id column="ID" jdbcType="BIGINT" property="id" />
<result column="HOST_NAME" jdbcType="VARCHAR" property="hostName" />
<result column="PORT" jdbcType="VARCHAR" property="port" />
<result column="TYPE" jdbcType="INTEGER" property="type" />
<result column="LAUNCH_DATE" jdbcType="DATE" property="launchDate" />
<result column="MODIFIED" jdbcType="TIMESTAMP" property="modified" />
<result column="CREATED" jdbcType="TIMESTAMP" property="created" />
</resultMap>
<insert id="addWorkerNode" useGeneratedKeys="true" keyProperty="id"
parameterType="com.xfvape.uid.worker.entity.WorkerNodeEntity">
INSERT INTO WORKER_NODE
(HOST_NAME,
PORT,
TYPE,
LAUNCH_DATE,
MODIFIED,
CREATED)
VALUES (
#{hostName},
#{port},
#{type},
#{launchDate},
NOW(),
NOW())
</insert>
<select id="getWorkerNodeByHostPort" resultMap="workerNodeRes">
SELECT
ID,
HOST_NAME,
PORT,
TYPE,
LAUNCH_DATE,
MODIFIED,
CREATED
FROM
WORKER_NODE
WHERE
HOST_NAME = #{host} AND PORT = #{port}
</select>
</mapper>
配置cache id :cached-uid-spring.xml
放在resources/uid文件夹下面:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- UID generator -->
<bean id="disposableWorkerIdAssigner" class="com.xfvape.uid.worker.DisposableWorkerIdAssigner" />
<bean id="cachedUidGenerator" class="com.xfvape.uid.impl.CachedUidGenerator">
<property name="workerIdAssigner" ref="disposableWorkerIdAssigner" />
<property name="epochStr" value="2019-06-14"/>
<!-- 以下为可选配置, 如未指定将采用默认值 -->
<!-- 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>-->
<!-- 拒绝策略: 当环已满, 无法继续填充时 -->
<!-- 默认无需指定, 将丢弃Put操作, 仅日志记录. 如有特殊需求, 请实现RejectedPutBufferHandler接口(支持Lambda表达式) -->
<!--<property name="rejectedPutBufferHandler" ref="XxxxYourPutRejectPolicy"></property>-->
<!-- 拒绝策略: 当环已空, 无法继续获取时 -->
<!-- 默认无需指定, 将记录日志, 并抛出UidGenerateException异常. 如有特殊需求, 请实现RejectedTakeBufferHandler接口(支持Lambda表达式) -->
<!--<property name="rejectedTakeBufferHandler" ref="XxxxYourTakeRejectPolicy"></property>-->
</bean>
<!-- Import mybatis config -->
<!--<import resource="classpath:/uid/mybatis-spring.xml" />-->
</beans>
spring boot 启动入口
主要就是加上注解@MapperScan("com.xfvape.uid")让mybatis能扫描到Mapper类的包的路径
@SpringBootApplication
@MapperScan("com.xfvape.uid")
public class NacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApplication.class, args);
}
}
创建配置文件: UidConfig类
@Configuration
@ImportResource(locations = { "classpath:uid/cached-uid-spring.xml" })
public class UidConfig {
}
创建服务接口:UidServiceImpl类
import com.xfvape.uid.UidGenerator;
import com.zz.nacosprovider.service.UidService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class UidServiceImpl implements UidService {
@Resource(name = "cachedUidGenerator")
private UidGenerator uidGenerator;
@Override
public long getUid() {
return uidGenerator.getUID();
}
}
主要说明一下@Resource(name = "cachedUidGenerator") 以往错误都是少了这里,没有标明注入来源
控制器:UidController 类
@RestController
public class UidController {
@Autowired
private UidService uidService;
@GetMapping("/uidGenerator")
public String UidGenerator() {
return String.valueOf(uidService.getUid());
}
}
项目配置文件:application.yml 和 application-dev.yml
application.yml
spring:
profiles:
active: dev
http:
encoding:
charset: UTF-8
enabled: true
force: true
server:
tomcat:
uri-encoding: UTF-8
mybatis:
#type-aliases-package: com.zz.nacosprovider.pojo
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
config: classpath:logback.xml
application-dev.yml
server:
port: 8762
spring:
application:
name: nacos-provider
#cloud:
#nacos:
#discovery:
#server-addr: 127.0.0.1:8848
#数据库连接配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
#driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.229.128:3306/nacos?characterEncoding=utf-8&useSSL=false
username: admin
password: 123456
#监控统计拦截的filters
druid:
#初始化连接数
initial-size: 5
#最小空闲连接数
min-idle: 5
#最大连接数
max-active: 20
#获取连接等待超时时间
max-wait: 60000
#间隔多久进行一次检测,检测需要关闭的空闲连接
time-between-eviction-runs-millis: 60000
#一个连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j
启动项目
从启动入口,启动
访问浏览器
因为是分布式生成id,所以需要继承分布式项目:使用Spring Cloud Alibaba:使用Nacos作为配置中心
pom.xml 取消spring-cloud-starter-alibaba-nacos-discovery注释
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.9.0.RELEASE</version>
</dependency>
启动类:
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.xfvape.uid")
@EnableConfigurationProperties
public class NacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApplication.class, args);
}
application-dev.yml 取消注释
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
启动成功,在浏览器上访问:http://localhost:8848/nacos,会跳转到登陆界面,默认的登陆用户名为nacos,密码也为nacos。
最后
以上就是朴实冷风为你收集整理的springboot2.x 集成百度 ui-dgenerator生成分布式唯一id的全部内容,希望文章能够帮你解决springboot2.x 集成百度 ui-dgenerator生成分布式唯一id所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复