springboot2接入百度UidGenerator

官方文档

UidGenerator源码地址
UidGenerator官方中文文档

接入步骤

1.下载源码并打包

由于UidGenerator没有上传jar包到maven仓库上,需要从GitHub上上面下载源码,自己打成jar包在引入到项目中;
下载UidGenerator源码后需要修改源码pom文件中的mybatis,mybatis-spring,mysql-connector-java这三个jar包的版本,版本号和自己springboot工程里面对应三个jar包的版本号一致,不然会导致引入UidGenerator后mybatis启动报错。


        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.5.1version>
        dependency>
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatis-springartifactId>
            <version>2.0.1version>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>8.0.17version>
            <scope>testscope>
        dependency>

2.springboot工程pom文件引入UidGenerator配置

在自己的项目中引入UidGenerator的maven配置,groupId,artifactId,version在自己本地打包时都可以任意修改

			
            <dependency>
                <groupId>com.baidu.fsggroupId>
                <artifactId>uid-generatorartifactId>
                <version>1.0.0-RELEASESversion>
            dependency>

3.本地数据库创建UidGenerator依赖的表结构

这一步跟官方文档的步骤一步骤二一样,有一点要注意,官方文档的MODIFIED,CREATED两个字段的类型都是TIMESTAMP,MySQL5.6以上的版本建表时可能会报:Error Code: 1067. Invalid default value for ‘CREATED’ 的错误,只要把字段类型修改为datetime 即可。SQL如下:

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 datetime NOT NULL COMMENT 'modified time',
CREATED datetime NOT NULL COMMENT 'created time',
PRIMARY KEY(ID)
)
 COMMENT='DB WorkerID Assigner for UID Generator',ENGINE = INNODB;

4.拷贝UidGenerator数据库操作相关文件

由于UidGenerator依赖于MySQL的WORKER_NODE表来辅助生成uid,需要在自己的项目中增加WORKER_NODE相关的mybatis操作类;

  1. 把WorkerNodeDAO拷贝到自己目录下,改名为WorkerNodeMapper;
  2. 把WORKER_NODE.xml文件拷贝到resource的目录下,改名为WorkerNodeMapper.xml,并把里面的namespace="com.baidu.fsg.uid.worker.dao.WorkerNodeDAO"改为自己项目中的WorkerNodeMapper;

springboot2接入百度UidGenerator_第1张图片
3. 拷贝DisposableWorkerIdAssigner类到自己的工程中,并把里面依赖的WorkerNodeDAO 改为本地新增的WorkerNodeMapper;
springboot2接入百度UidGenerator_第2张图片

/*
 * Copyright (c) 2017 Baidu, Inc. All Rights Reserve.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wangzhongxing.springcloud.dao.uidgenerator;

import com.baidu.fsg.uid.utils.DockerUtils;
import com.baidu.fsg.uid.utils.NetUtils;
import com.baidu.fsg.uid.worker.WorkerIdAssigner;
import com.baidu.fsg.uid.worker.WorkerNodeType;
import com.baidu.fsg.uid.worker.entity.WorkerNodeEntity;
import com.wangzhongxing.springcloud.dao.mapper.WorkerNodeMapper;
import org.apache.commons.lang.math.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * Represents an implementation of {@link WorkerIdAssigner},
 * the worker id will be discarded after assigned to the UidGenerator
 *
 * @author yutianbao
 */
@Component("disposableWorkerIdAssigner")
public class DisposableWorkerIdAssigner implements WorkerIdAssigner {

    private static final Logger LOGGER = LoggerFactory.getLogger(DisposableWorkerIdAssigner.class);

    @Resource
    private WorkerNodeMapper workerNodeMapper;

    /**
     * Assign worker id base on database.

* If there is host name & port in the environment, we considered that the node runs in Docker container
* Otherwise, the node runs on an actual machine. * * @return assigned worker id */ @Transactional public long assignWorkerId() { // build worker node entity WorkerNodeEntity workerNodeEntity = buildWorkerNode(); // add worker node for new (ignore the same IP + PORT) workerNodeMapper.addWorkerNode(workerNodeEntity); LOGGER.info("Add worker node:" + workerNodeEntity); return workerNodeEntity.getId(); } /** * Build worker node entity by IP and PORT */ private WorkerNodeEntity buildWorkerNode() { WorkerNodeEntity workerNodeEntity = new WorkerNodeEntity(); if (DockerUtils.isDocker()) { workerNodeEntity.setType(WorkerNodeType.CONTAINER.value()); workerNodeEntity.setHostName(DockerUtils.getDockerHost()); workerNodeEntity.setPort(DockerUtils.getDockerPort()); } else { workerNodeEntity.setType(WorkerNodeType.ACTUAL.value()); workerNodeEntity.setHostName(NetUtils.getLocalAddress()); workerNodeEntity.setPort(System.currentTimeMillis() + "-" + RandomUtils.nextInt(100000)); } return workerNodeEntity; } }

  1. 修改@MapperScan注解,添加com.baidu.fsg.uid包,例如:@MapperScan(basePackages = {“com.wangzhongxing.springcloud.dao.mapper”, “com.baidu.fsg.uid”})
  2. 修改mybatis.mapper-locations配置,增加WorkerNodeMapper.xml所在的路径,我是放到了mybatis/mapping/custom/目录下:
#mybatis配置
mybatis:
# 指定全局配置文件位置
  config-location: classpath:mybatis/mybatis-config.xml
  # 指定sql映射文件位置
  mapper-locations: classpath:mybatis/mapping/auto/*.xml,classpath:mybatis/mapping/custom/*.xml
  type-aliases-package: com.wangzhongxing.springcloud.dao.dataobject

5.添加UidGenerator相关bean配置

初始化DisposableWorkerIdAssigner,CachedUidGenerator 这两个bean,初始化配置如下:

package com.wangzhongxing.springcloud.dao.uidgenerator;

import com.baidu.fsg.uid.impl.CachedUidGenerator;
import com.baidu.fsg.uid.impl.DefaultUidGenerator;
import com.baidu.fsg.uid.worker.WorkerIdAssigner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Auther: wangzhongxing
 * @Date: 2020/1/13 17:52
 * @Description: https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md
 * 

* 接入指引文档:https://blog.csdn.net/weixin_39338423/article/details/103972134 *

* 百度id生成器 * 两种生成器: DefaultUidGenerator、CachedUidGenerator。如对UID生成性能有要求, 请使用CachedUidGenerator * 对应Spring配置分别为: default-uid-spring.xml、cached-uid-spring.xml */ @Configuration public class CachedUidGeneratorConfig { /** * disposableWorkerIdAssigner的入参对象类型最好使用 WorkerIdAssigner, * 否则其他地方引入CGLib动态代理的时候可能会导致代理混用的问题 * * @param disposableWorkerIdAssigner * @return */ @Bean public DefaultUidGenerator defaultUidGenerator(WorkerIdAssigner disposableWorkerIdAssigner) { DefaultUidGenerator defaultUidGenerator = new DefaultUidGenerator(); defaultUidGenerator.setWorkerIdAssigner(disposableWorkerIdAssigner); /** * 关于UID比特分配的建议: * 对于并发数要求不高、期望长期使用的应用, 可增加timeBits位数, 减少seqBits位数. * 例如节点采取用完即弃的WorkerIdAssigner策略, 重启频率为12次/天, 那么配置成: * {"workerBits":23,"timeBits":31,"seqBits":9}时, 可支持28个节点以整体并发量14400 UID/s的速度持续运行68年. * * 对于节点重启频率频繁、期望长期使用的应用, 可增加workerBits和timeBits位数, 减少seqBits位数. * 例如节点采取用完即弃的WorkerIdAssigner策略, 重启频率为24*12次/天, 那么配置成: * {"workerBits":27,"timeBits":30,"seqBits":6}时, 可支持37个节点以整体并发量2400 UID/s的速度持续运行34年. */ // 以下为可选配置, 如未指定将采用默认值 // timeBits,相对于时间基点"2016-05-20"的增量值,单位:秒,可使用的时间为2^timeBis 秒 // 例如:timeBits=30,则可使用2^30秒,约34年,timeBits=31,则可使用2^31秒,约68年 defaultUidGenerator.setTimeBits(32); // 机器id,最多可支持2^22约420w次机器启动。内置实现为在启动时由数据库分配,默认分配策略为用后即弃, // 每次启动都会重新生成一批ID,因此重启次数也是会有限制的,后续可提供复用策略。 defaultUidGenerator.setWorkerBits(22); // 每秒下的并发序列,9 bits可支持每台服务器每秒512个并发。 defaultUidGenerator.setSeqBits(9); defaultUidGenerator.setEpochStr("2020-01-01"); return defaultUidGenerator; } /** * disposableWorkerIdAssigner的入参对象类型最好使用 WorkerIdAssigner, * 否则其他地方引入CGLib动态代理的时候可能会导致代理混用的问题 * * @param disposableWorkerIdAssigner * @return */ @Bean public CachedUidGenerator cachedUidGenerator(WorkerIdAssigner disposableWorkerIdAssigner) { CachedUidGenerator cachedUidGenerator = new CachedUidGenerator(); cachedUidGenerator.setWorkerIdAssigner(disposableWorkerIdAssigner); /** * 关于UID比特分配的建议: * 对于并发数要求不高、期望长期使用的应用, 可增加timeBits位数, 减少seqBits位数. * 例如节点采取用完即弃的WorkerIdAssigner策略, 重启频率为12次/天, 那么配置成: * {"workerBits":23,"timeBits":31,"seqBits":9}时, 可支持28个节点以整体并发量14400 UID/s的速度持续运行68年. * * 对于节点重启频率频繁、期望长期使用的应用, 可增加workerBits和timeBits位数, 减少seqBits位数. * 例如节点采取用完即弃的WorkerIdAssigner策略, 重启频率为24*12次/天, 那么配置成: * {"workerBits":27,"timeBits":30,"seqBits":6}时, 可支持37个节点以整体并发量2400 UID/s的速度持续运行34年. */ // 以下为可选配置, 如未指定将采用默认值 // timeBits,相对于时间基点"2016-05-20"的增量值,单位:秒,可使用的时间为2^timeBis 秒 // 例如:timeBits=30,则可使用2^30秒,约34年,timeBits=31,则可使用2^31秒,约68年 cachedUidGenerator.setTimeBits(32); // 机器id,最多可支持2^22约420w次机器启动。内置实现为在启动时由数据库分配,默认分配策略为用后即弃, // 每次启动都会重新生成一批ID,因此重启次数也是会有限制的,后续可提供复用策略。 cachedUidGenerator.setWorkerBits(22); // 每秒下的并发序列,9 bits可支持每台服务器每秒512个并发。 cachedUidGenerator.setSeqBits(9); cachedUidGenerator.setEpochStr("2020-01-01"); //RingBuffer size扩容参数, 可提高UID生成的吞吐量 //默认:3, 原bufferSize=8192, 扩容后bufferSize= 8192 << 3 = 65536 cachedUidGenerator.setBoostPower(3); // 指定何时向RingBuffer中填充UID, 取值为百分比(0, 100), 默认为50 // 举例: bufferSize=1024, paddingFactor=50 -> threshold=1024 * 50 / 100 = 512. // 当环上可用UID数量 < 512时, 将自动对RingBuffer进行填充补全 // //另外一种RingBuffer填充时机, 在Schedule线程中, 周期性检查填充 //默认:不配置此项, 即不实用Schedule线程. 如需使用, 请指定Schedule线程时间间隔, 单位:秒 cachedUidGenerator.setScheduleInterval(60L); //拒绝策略: 当环已满, 无法继续填充时 //默认无需指定, 将丢弃Put操作, 仅日志记录. 如有特殊需求, 请实现RejectedPutBufferHandler接口(支持Lambda表达式) // //cachedUidGenerator.setRejectedPutBufferHandler(); //拒绝策略: 当环已空, 无法继续获取时 --> //默认无需指定, 将记录日志, 并抛出UidGenerateException异常. 如有特殊需求, 请实现RejectedTakeBufferHandler接口(支持Lambda表达式) --> // return cachedUidGenerator; } }

6.使用CachedUidGenerator 生成uid

只需引入cachedUidGenerator bean实例,直接调用cachedUidGenerator.getUID()方法即可生成uid

package com.wangzhongxing.springcloud;

import com.baidu.fsg.uid.UidGenerator;
import com.wangzhongxing.springcloud.web.SpringcloudTemplateWebApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @Auther: wangzhongxing
 * @Date: 2020/1/14 14:57
 * @Description:
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringcloudTemplateWebApplication.class)
public class CachedUidGeneratorTest {

    @Autowired
    private UidGenerator cachedUidGenerator;

    @Test
    public void getUidTest() {
        Long uid = cachedUidGenerator.getUID();

        System.out.println(uid);
    }

}

每生成一个uid都会往WORKER_NODE表中插入一条记录
springboot2接入百度UidGenerator_第3张图片

你可能感兴趣的:(Java)