springboot集成uid-generator生成分布式id

一、简介

uid-generator是由百度技术部开发,GitHub地址

UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器

Snowflake算法

Snowflake算法描述:指定机器 & 同一时刻 & 某一并发序列,是唯一的。据此可生成一个64 bits的唯一ID(long)。默认采用上图字节分配方式:

sign(1bit) 固定1bit符号标识,即生成的UID为正数。
delta seconds (28 bits) 当前时间,相对于时间基点"2016-05-20"的增量值,单位:秒,最多可支持约8.7年
worker id (22 bits) 机器id,最多可支持约420w次机器启动。内置实现为在启动时由数据库分配,默认分配策略为用后即弃,后续可提供复用策略。
sequence (13 bits) 每秒下的并发序列,13 bits可支持每秒8192个并发。

二、使用Spring boot项目集成uid-generator

2.1 将项目下载之后生成文件

下载完成后使用IDEA打开

复制生成的文件夹到maven仓库

我的maven仓库安装到了d盘

之后就可以使用标签引入了

2.2项目中引入uid-generator依赖,并排除其中的mybatis依赖

如果项目是SpringBoot+Mybatisplus,UidGenerator是Spring+Mybatis,直接引入uid-generator之后,本地项目启动就会出现创建SqlSessionFactory报错,所以,直接将uid-generator中的mybatis相关依赖排除。避免出现不必要的启动问题

复制代码
<dependency>
    <groupId>com.baidu.fsg</groupId>
    <artifactId>uid-generator</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <exclusions>
        <exclusion>
            <groupId>org.mybatis</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2.3 创建数据库表

复制代码
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;

2.4 生成实体类与mapper

2.4.1实体类
复制代码
import java.util.Date;

public class WorkerNode {

    private Long id;

    private String hostName;

    private String port;

    private Integer type;

    private Date LaunchDate;

    private Date modified;

    private Date created;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getHostName() {
        return hostName;
    }

    public void setHostName(String hostName) {
        this.hostName = hostName;
    }

    public String getPort() {
        return port;
    }

    public void setPort(String port) {
        this.port = port;
    }

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public Date getLaunchDate() {
        return LaunchDate;
    }

    public void setLaunchDate(Date launchDate) {
        LaunchDate = launchDate;
    }

    public Date getModified() {
        return modified;
    }

    public void setModified(Date modified) {
        this.modified = modified;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    @Override
    public String toString() {
        return "WorkerNode{" +
                "id=" + id +
                ", hostName='" + hostName + '\'' +
                ", port='" + port + '\'' +
                ", type=" + type +
                ", LaunchDate=" + LaunchDate +
                ", modified=" + modified +
                ", created=" + created +
                '}';
    }
}
2.4.2 mapper与mapper.xml
复制代码
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface WorkerNodeMapper {

    int addWorkerNode(WorkerNode workerNodeEntity);


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

}

<?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.lq.mapper.WorkerNodeMapper">
    <resultMap id="BaseResultMap"
               type="com.lq.entity.pojo.WorkerNode">
        <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.lq.entity.pojo.WorkerNode">
        INSERT INTO WORKER_NODE
        (HOST_NAME,
         PORT,
         TYPE,
         LAUNCH_DATE,
         MODIFIED,
         CREATED)
        VALUES (
                   #{hostName},
                   #{port},
                   #{type},
                   #{launchDate},
                   NOW(),
                   NOW())
    </insert>

    <select id="getWorkerNodeByHostPort" resultMap="BaseResultMap">
        SELECT
            ID,
            HOST_NAME,
            PORT,
            TYPE,
            LAUNCH_DATE,
            MODIFIED,
            CREATED
        FROM
            WORKER_NODE
        WHERE
            HOST_NAME = #{host} AND PORT = #{port}
    </select>
</mapper>

注:

修改对应位置为自己实体类与mapper所在位置

2.5 service与impl

  • service
java 复制代码
/**
 * @注释
 */
public interface IWorkerNodeService {

    public long genUid();
}
  • serviceimpl
java 复制代码
import com.baidu.fsg.uid.UidGenerator;
import com.lq.service.IWorkerNodeService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 */
@Service
public class WorkerNodeServiceImpl implements IWorkerNodeService {
    @Resource
    private UidGenerator uidGenerator;

    @Override
    public long genUid() {
        return uidGenerator.getUID();
    }
}

2.6 添加配置类

2.6.1 DisposableWorkerIdAssigner
复制代码
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 org.apache.commons.lang.math.RandomUtils;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;

/**
 */
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;
    }
}
2.6.2 WorkerNodeConfig
复制代码
import com.baidu.fsg.uid.UidGenerator;
import com.baidu.fsg.uid.impl.CachedUidGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** 
 */
@Configuration
public class WorkerNodeConfig {

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

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

2.7 测试

复制代码
import com.lq.service.IWorkerNodeService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 */
@SpringBootTest
public class UidGenerateTest {

    @Resource
    private IWorkerNodeService workerNodeService;

    @Test
    public void getUid() {
        List<Long> list = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            long uid = workerNodeService.genUid();
            list.add(uid);
        }
        AtomicInteger num = new AtomicInteger();
        list.forEach(l -> {
            System.out.println("第" + num.getAndIncrement() + "个id为 = " + l);
        });
    }
}
相关推荐
秃头菜狗21 小时前
十一、Hadoop 三种部署模式对比表 & 组件介绍
分布式
梦飞翔2381 天前
Spring Boot
spring boot
青柠编程1 天前
基于Spring Boot的选课管理系统架构设计
java·spring boot·后端
前端橙一陈1 天前
LocalStorage Token vs HttpOnly Cookie 认证方案
前端·spring boot
nlog3n1 天前
分布式短链接系统设计方案
java·分布式
每次的天空1 天前
Android -Glide实战技术总结
java·spring boot·spring
码事漫谈1 天前
C++内存泄漏排查:从基础到高级的完整工具指南
后端
王嘉俊9251 天前
ThinkPHP 入门:快速构建 PHP Web 应用的强大框架
开发语言·前端·后端·php·框架·thinkphp
码事漫谈1 天前
C++多线程数据竞争:从检测到修复的完整指南
后端
Code blocks1 天前
SpringBoot快速生成二维码
java·spring boot·后端