UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器。UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略, 从而适用于docker等虚拟化环境下实例自动重启、漂移等场景。 在实现上, UidGenerator通过借用未来时间来解决sequence天然存在的并发限制; 采用RingBuffer来缓存已生成的UID, 并行化UID的生产和消费, 同时对CacheLine补齐,避免了由RingBuffer带来的硬件级「伪共享」问题. 最终单机QPS可达600万。

官方地址:https://github.com/baidu/uid-generator

uid-generator提供了两种生成器: DefaultUidGenerator、CachedUidGenerator。如对UID生成性能有要求, 请使用CachedUidGenerator

CachedUidGenerator

RingBuffer环形数组,数组每个元素成为一个slot。RingBuffer容量,默认为Snowflake算法中sequence最大值,且为2^N。可通过boostPower配置进行扩容,以提高RingBuffer 读写吞吐量。

Tail指针、Cursor指针用于环形数组上读写slot:

  • Tail指针
    表示Producer生产的最大序号(此序号从0开始,持续递增)。Tail不能超过Cursor,即生产者不能覆盖未消费的slot。当Tail已赶上curosr,此时可通过rejectedPutBufferHandler指定PutRejectPolicy
  • Cursor指针
    表示Consumer消费到的最小序号(序号序列与Producer序列相同)。Cursor不能超过Tail,即不能消费未生产的slot。当Cursor已赶上tail,此时可通过rejectedTakeBufferHandler指定TakeRejectPolicy

CachedUidGenerator采用了双RingBuffer,Uid-RingBuffer用于存储Uid、Flag-RingBuffer用于存储Uid状态(是否可填充、是否可消费)

由于数组元素在内存中是连续分配的,可最大程度利用CPU cache以提升性能。但同时会带来「伪共享」FalseSharing问题,为此在Tail、Cursor指针、Flag-RingBuffer中采用了CacheLine 补齐方式。

RingBuffer填充时机

  • 初始化预填充
    RingBuffer初始化时,预先填充满整个RingBuffer.
  • 即时填充
    Take消费时,即时检查剩余可用slot量(tail - cursor),如小于设定阈值,则补全空闲slots。阈值可通过paddingFactor来进行配置,请参考Quick Start中CachedUidGenerator配置
  • 周期填充
    通过Schedule线程,定时补全空闲slots。可通过scheduleInterval配置,以应用定时填充功能,并指定Schedule时间间隔

1、导入依赖

<!-- https://mvnrepository.com/artifact/com.xfvape.uid/uid-generator -->
<dependency><groupId>com.xfvape.uid</groupId><artifactId>uid-generator</artifactId><version>0.0.4-RELEASE</version>
</dependency>

2、创建表WORKER_NODE

运行sql脚本以导入表WORKER_NODE, 脚本如下:

DROP DATABASE IF EXISTS `xxxx`;
CREATE DATABASE `xxxx` ;
use `xxxx`;
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;

3、maven依赖

 <dependencies><dependency><groupId>com.xiaobear.distributedid</groupId><artifactId>distributedid-core</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.0</version></dependency><!--必须放在最后--><!-- https://mvnrepository.com/artifact/com.xfvape.uid/uid-generator --><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></dependencies>

4、配置文件

spring:datasource:type: com.zaxxer.hikari.HikariDataSourceurl: jdbc:mysql://127.0.0.1:3306/distributedid?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=false&autoReconnect=trueusername: rootpassword: 密码driver-class-name: com.mysql.cj.jdbc.Driver
server:port: 8088mybatis:type-aliases-package: com.xiaobear.distributedid.core.domainmapper-locations: classpath*:mapper/*.xml

5、主启动类

@SpringBootApplication
@MapperScan("com.xiaobear.distributedid.mapper")
public class UidgeneratorApplication {public static void main(String[] args) {SpringApplication.run(UidgeneratorApplication.class);System.out.println("百度生成ID 启动成功");}
}

6、业务类

1、实体类
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) {this.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;}@Overridepublic String toString() {return "WorkerNode{" +"id=" + id +", hostName='" + hostName + '\'' +", port='" + port + '\'' +", type=" + type +", launchDate=" + launchDate +", modified=" + modified +", created=" + created +'}';}
}
2、数据层接口
@Mapper
public interface WorkerNodeMapper {/*** 添加对象* @param workerNodeEntity* @return*/int addWorkerNode(WorkerNode workerNodeEntity);/*** 通过host port 获取ID* @param host* @param port* @return*/WorkerNode getWorkerNodeByHostPort(@Param("host") String host, @Param("port") String port);
}

mapper.xml

<?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.xiaobear.distributedid.mapper.WorkerNodeMapper"><resultMap id="workerNodeRes" type="com.xiaobear.distributedid.core.domain.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.xiaobear.distributedid.core.domain.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="workerNodeRes">SELECTID,HOST_NAME,PORT,TYPE,LAUNCH_DATE,MODIFIED,CREATEDFROMWORKER_NODEWHEREHOST_NAME = #{host} AND PORT = #{port}</select>
</mapper>
3、实现层接口
public interface IWorkerNodeService {/*** 获取ID* @return*/public long genUid();
}
4、实现层实现类
@Service
public class WorkerNodeServiceImpl implements IWorkerNodeService {@Resourceprivate UidGenerator uidGenerator;/*** 获取百度生成ID* @return*/@Overridepublic long genUid() {return uidGenerator.getUID();}
}
5、控制层接口
@RestController
public class WorkerNodeController {@Resourceprivate IWorkerNodeService workerNodeService;/***使用百度 Uidgenerator获取ID* @return*/@GetMapping("/Uidgenerator")public RestResponse getIdByBaiDuUid(){long id = workerNodeService.genUid();return RestResponse.success(id);}
}

7、测试

http://localhost:8088/Uidgenerator

{"code":200,"msg":"成功","result":7067247636209745920}

8、uid-generator核心对象装配为spring的bean

1、重写WorkerIdAssigner接口

public class DisposableWorkerIdAssigner implements WorkerIdAssigner{@Resourceprivate WorkerNodeMapper workerNodeMapper;@Override@Transactional(rollbackFor = Exception.class)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());} else {workNode.setType(WorkerNodeType.ACTUAL.value());workNode.setHostName(NetUtils.getLocalAddress());workNode.setPort(System.currentTimeMillis() + "-" + RandomUtils.nextInt(100000));}workNode.setLaunchDate(new Date());return workNode;}
}

2、自动转配bean

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

3、使用,在实现类指定生成ID的bean

@Service
public class WorkerNodeServiceImpl implements IWorkerNodeService {@Resource(name = "cachedUidGenerator")private UidGenerator uidGenerator;/*** 获取百度生成ID* @return*/@Overridepublic long genUid() {return uidGenerator.getUID();}
}

Spring Boot 集成百度 Uidgenerator分布式ID生成器相关推荐

  1. SpringBoot集成百度uid-generator唯一ID生成器

    大家好,我是猿人(猿码天地创始人),今天给码农们或即将成为码农或想成为码农的朋友讲讲SpringBoot集成百度uid-generator唯一ID生成器,现在是深夜23:10分,猿人最擅长熬夜,就是不 ...

  2. SpringBoot2.0集成百度uid-generator唯一ID生成器,支持zk、redis、数据库进行WORKER ID分配

    UidGenerator是百度开源的基于Snowflake算法的唯一ID生成器,使用java语言实现,可在分布式环境下生成单调递增的ID.详情参见: uid-generator 从官网说明或者网上的使 ...

  3. 百度开源分布式id生成器uid-generator源码剖析

    百度uid-generator源码 https://github.com/baidu/uid-generator snowflake算法 uid-generator是基于Twitter开源的snowf ...

  4. 百度开源的分布式 ID 生成器,太强大了!

    来源:https://lilinchao.com/archives/1226.html 一.UidGenerator是什么 UidGenerator是百度开源的一款分布式高性能的唯一ID生成器,是基于 ...

  5. 融云发送图片消息_IM消息ID技术专题(五):开源分布式ID生成器UidGenerator的技术实现...

    1.引言 很多人一想到IM应用开发,第一印象就是"长连接"."socket"."保活"."协议"这些关键词,没错,这些确 ...

  6. IM消息ID技术专题(五):开源分布式ID生成器UidGenerator的技术实现

    1.引言 很多人一想到IM应用开发,第一印象就是"长连接"."socket"."保活"."协议"这些关键词,没错,这些确 ...

  7. Spring Boot集成Hazelcast实现集群与分布式内存缓存

    2019独角兽企业重金招聘Python工程师标准>>> Hazelcast是Hazelcast公司开源的一款分布式内存数据库产品,提供弹性可扩展.高性能的分布式内存计算.并通过提供诸 ...

  8. 开源分布式ID生成器UidGenerator的技术实现

    1.引言 很多人一想到IM应用开发,第一印象就是"长连接"."socket"."保活"."协议"这些关键词,没错,这些确 ...

  9. 基于号段模式、百度UID实现的分布式ID生成器kylin-id

    1.简介 1.1.开源项目 kylin-id:麒麟分布式id生成器,支持号段模式.雪花算法 并未发布jar到中央仓库,需要自己本地构建 1.2.介绍 参考滴滴[tinyid] 整合百度[UID] 麒麟 ...

最新文章

  1. centos7安装JDK1.7
  2. Flink1.7.2 sql 批处理示例
  3. linux运维、架构之路-MySQL多实例
  4. flir红外数据集_设备停机导致损失惨重?FLIR红外自动化解决方案了解一下
  5. 各种卡的一些信息积累
  6. Coursera课程Python for everyone:Quiz: Networks and Sockets
  7. Qt 原理-MOC(2) QObject.h
  8. 骑士周游算法 c语言_C语言经典算法04--骑士走棋盘(骑士旅游:Knight tour)
  9. 2017.0612.《计算机组成原理》总线结构
  10. elasticsearch api中的delete操作
  11. Sql Server2005对t-sql的增强之Cross Apply
  12. Linux_linux常用工具---闲杂篇(除了vim, 还有哪些常用的牛逼的编辑器, 并能够横向对比编辑器之间的区别和优缺点.)
  13. python类和对象的定义_day15_python_类和对象
  14. WAP的技术、运动和现状(转)
  15. https://www.jb51.net/article/146628.htm
  16. 亚马逊广告投放策略卖家们知多少?
  17. python输入一个浮点数、输出其整数部分和小数部分_输入一个浮点数,并输出该数的整数部分和小数部分...
  18. openwrt修改logo
  19. 【每日新闻】国内首款3D AI/MR芯片即将量产
  20. 抢红包算法--四种抢红包算法对比(附源码)

热门文章

  1. 开发电竞竞猜产品如设计赔率模块?
  2. 国外电子证据及计算机法证技术发展近况
  3. 【云栖大会】阿里金融云总经理徐敏:金融云时代计算、连接与信任
  4. 强制关闭miui12.5充电提示音,亲测可用
  5. QGIS如何绘制地图,WMS为例
  6. IOS 学习 gei post 同步 异步方法
  7. 【转】机器人上用的传感器的介绍
  8. MySQL学习003:利用ExecuteScalar查询
  9. 公司引进企业微信有什么重要的意义?
  10. 《拆掉思维里的墙》 古典 (初读此书,相见恨晚!)