SpringBoot2.x整合百度UidGenerator

語言: CN / TW / HK

一、UidGenerator是什麼

UidGenerator是百度開源的一款分散式高效能的唯一ID生成器,是基於snowflake模型的一種ID生成器

二、UidGenerator的優勢

1.解決了時鐘回撥的問題

2.使用ringbuffer,無鎖進行id的生產與消費,速度非常快

3.適用於多執行緒,不會有單執行緒瓶頸

三、整合

本次通過SpringBoot2.x和MyBatis對百度UidGenerator進行整合。

3.1 UidGenerator引入

一般使用兩種方式引入UidGenerator:

(1)從官網下載原始碼作為自己專案的一個Module引入到專案中

官網地址:https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

(2)網際網路jar包引入(本文采取的是該種方式)

因為UidGenerator自帶引入了mybatis,和自己專案有衝突的可以進行排除

xml <dependency> <groupId>com.xfvape.uid</groupId> <artifactId>uid-generator</artifactId> <version>0.0.4-RELEASE</version> </dependency>

排除衝突依賴

uid-generator中依賴了logback和mybatis。一般在專案搭建過程中,springboot中已經有了logback依賴,mybatis會作為單獨的依賴引入。如果版本和uid-generator中的依賴不一致的話,就會導致衝突。

排除衝突的依賴如下:

xml <dependency> <groupId>com.xfvape.uid</groupId> <artifactId>uid-generator</artifactId> <version>0.0.4-RELEASE</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> </exclusion> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclusion> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> <exclusion> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> </exclusion> <exclusion> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> </exclusion> </exclusions> </dependency>

3.2 建立表

在 MySQL資料庫中建一個名為 WORKER_NODE的資料表,其 sql如下:

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 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;

建表時可能會報錯,原因是該建表語句定義了兩個TIMESTAMP欄位,因為mysql 低版本控制比較嚴格

解決辦法:

方式一:

直接把TIMESTAMP改成DATETIME 即可

方式二:

建表前先設定sql_mode:

sql set sql_mode="NO_ENGINE_SUBSTITUTION";

3.3 將uid-generator核心物件裝配為spring的bean

uid-generator提供了兩種生成器: DefaultUidGeneratorCachedUidGenerator。如對UID生成效能有要求, 請使用CachedUidGenerator。

```java @Configuration public class WorkerNodeConfig {

@Bean("disposableWorkerIdAssigner")
public DisposableWorkerIdAssigner disposableWorkerIdAssigner(){
    DisposableWorkerIdAssigner disposableWorkerIdAssigner = new DisposableWorkerIdAssigner();
    return  disposableWorkerIdAssigner;
}

@Bean("cachedUidGenerator")
public UidGenerator uidGenerator(DisposableWorkerIdAssigner disposableWorkerIdAssigner){
    CachedUidGenerator cachedUidGenerator = new CachedUidGenerator();
    cachedUidGenerator.setWorkerIdAssigner(disposableWorkerIdAssigner);
    return cachedUidGenerator;
}

} ```

直接建立WorkerNodeConfig類,複製以上程式碼。

3.4 重寫WorkerIdAssigner介面

```java public class DisposableWorkerIdAssigner implements WorkerIdAssigner {

@Resource
private WorkerNodeMapper workerNodeMapper;
@Override
@Transactional
public long assignWorkerId() {
    WorkerNode workerNode = buildWorkerNode();

    workerNodeMapper.addWorkerNode(workerNode);

    return workerNode.getId();
}

private WorkerNode buildWorkerNode() {
    WorkerNode workNode = new WorkerNode();
    if (DockerUtils.isDocker()) {
        workNode.setType(WorkerNodeType.CONTAINER.value());
        workNode.setHostName(DockerUtils.getDockerHost());
        workNode.setPort(DockerUtils.getDockerPort());
        workNode.setLaunchDate(new Date());
    } else {
        workNode.setType(WorkerNodeType.ACTUAL.value());
        workNode.setHostName(NetUtils.getLocalAddress());
        workNode.setPort(System.currentTimeMillis() + "-" + RandomUtils.nextInt(100000));
        workNode.setLaunchDate(new Date());
    }

    return workNode;
}

} ```

建立一個DisposableWorkerIdAssigner類直接複製以上程式碼。

3.5 引入WorkerNodeMapper.xml

```xml

INSERT INTO WORKER_NODE (HOST_NAME, PORT, TYPE, LAUNCH_DATE, MODIFIED, CREATED) VALUES ( #{hostName}, #{port}, #{type}, #{launchDate}, NOW(), NOW())

```

可以通過mybatis生成工具直接生成檔案和實體類,然後將插入和查詢方法複製

注意修改resultMap中的type和insert中的keyProperty為自身專案的實體類地址

在application.yml檔案中增加如下配置

yml mybatis: mapper-locations: classpath:mybatis/*.xml

3.6實體類

使用外掛生成的實體類

3.7建立Mapper

```java @Mapper public interface WorkerNodeMapper {

int addWorkerNode(WorkerNode workerNodeEntity);


WorkerNode getWorkerNodeByHostPort(@Param("host") String host, @Param("port") String port);

} ```

3.8 Service

IWorkerNodeService介面

java public interface IWorkerNodeService { public long genUid(); }

WorkerNodeServiceImpl實現類

```java @Service public class WorkerNodeServiceImpl implements IWorkerNodeService { @Resource private UidGenerator uidGenerator;

@Override
public long genUid() {
    Long uu_id = UidGeneratorComponent.uu_id;
    return uidGenerator.getUID();
}

} ```

3.8 Controller

java @RestController public class WorkerNodeServiceController { @Resource private IWorkerNodeService workerNodeService; /** * 整合百度uid-generator生成id * @return */ @GetMapping("/baidu/uid") public long baiduUid(){ long uid = workerNodeService.genUid(); return uid; } }

3.9 訪問介面測試

http://127.0.0.1:8099/test/baidu/uid

2.SpringBoot2.x整合百度uid-generator.jpg

專案目錄結構

2.SpringBoot2.x整合百度uid-generator02.jpg