我是靠谱客的博主 朴实冷风,最近开发中收集的这篇文章主要介绍springboot2.x 集成百度 ui-dgenerator生成分布式唯一id,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

百度的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所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部