# uid-generator-springboot **Repository Path**: guoweixin/uid-generator-springboot ## Basic Information - **Project Name**: uid-generator-springboot - **Description**: 基于分布式id 百度开源UidGenerator整合SpringBoot案例 UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 11 - **Created**: 2021-08-15 - **Last Updated**: 2024-07-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # uid-generator-springboot #### 介绍 基于分布式id 百度开源UidGenerator整合SpringBoot案例 UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器。 参考视频: https://www.bilibili.com/video/BV1CL411778r?p=82 # 分布式ID ## 应用场景 ```bat 在业务系统中很多场景下需要生成不重复的 ID,比如京东订单编号、飞机票订单号、外卖订单号、支付流水单号、优惠券编号等都需要使用到。账户进行标识,以一个有意义的有序的序列号来作为全局唯一的ID。 以京东为例,为了保证(用户信息安全),可通过订单编号查询到:商家信息、买家信息、物流信息、等关联全部信息。 ``` ![输入图片说明](https://images.gitee.com/uploads/images/2021/0815/230745_5839406a_720177.png "1.png") ## 分布式ID特点 ```bat 分布式系统中我们对ID生成器要求又有哪些呢? 1. 全局唯一性:不能出现重复的ID号,既然是唯一标识,这是最基本的要求。 2. 简洁/直观:(生成的ID号)客户用于关联其它业务的唯一重要凭证。 3. 高并发 4. 高性能 5. 高可用 ``` 系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结。 ## 解决方案 **1. 基于数据库方案** **2. UUID** **3. Redis生成ID** **4. Twitter的snowflake算法** **5. 利用zookeeper生成唯一ID** # 分布式解决方案描述 ## SnowFlake算法 ```bat snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。 官方代码:https://github.com/twitter/snowflake。雪花算法支持的TPS可以达到419万左右(2^22*1000)。 雪花算法在工程实现上有单机版本和分布式版本。单机版本如下, 分布式版本可以参看美团leaf算法:https://github.com/Meituan-Dianping/Leaf 百度封装并开源:uid-generator https://github.com/baidu/uid-generator ``` ### 百度uid-generator 唯一ID生成器 ```bat UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器。UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略, 从而适用于docker等虚拟化环境下实例自动重启、漂移等场景。 在实现上, UidGenerator通过借用未来时间来解决sequence天然存在的并发限制; 采用RingBuffer来缓存已生成的UID, 并行化UID的生产和消费, 同时对CacheLine补齐,避免了由RingBuffer带来的硬件级「伪共享」问题. 最终单机QPS可达600万。依赖版本:Java8及以上版本, MySQL(内置WorkerID分配器, 启动阶段通过DB进行分配; 如自定义实现, 则DB非必选依赖) ``` **中文文档** **官方源码** ## 代码实战 ### 架构如下依次创建 ```bat chapter-disributed-id 父工程(pom) uid-generator jar(普通jar) boot-disributed-id jar[8080]微服务 SSM操作 ``` ### MySQL创建表WORKER_NODE ```sql 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; ``` ### 官方源码下载 https://github.com/baidu/uid-generator/ **创建uid-generator 普通jar 子工程** ![输入图片说明](https://images.gitee.com/uploads/images/2021/0815/230829_d05ee64e_720177.png "2.png") **pom.xml** ```bat chapter-distributed-id com.qfjy 1.0-SNAPSHOT 4.0.0 uid-generator uid-generator http://www.example.com UTF-8 1.8 4.2.5.RELEASE 1.7.7 commons-collections commons-collections 3.2.2 commons-lang commons-lang 2.6 ``` ### 创建微服务子工程boot-disributed-id SpringBoot SSM整合(此处忽略) **导入上方支持依赖jar** ```bat com.qfjy uid-generator 1.0-SNAPSHOT ``` ![输入图片说明](https://images.gitee.com/uploads/images/2021/0815/230846_009c1362_720177.png "3.png") ### 配置生成器 cached-uid-spring.xml 提供了两种生成器: [DefaultUidGenerator](https://github.com/baidu/uid-generator/blob/master/src/main/java/com/baidu/fsg/uid/impl/DefaultUidGenerator.java)、[CachedUidGenerator](https://github.com/baidu/uid-generator/blob/master/src/main/java/com/baidu/fsg/uid/impl/CachedUidGenerator.java)。 如对UID生成性能有要求, 请使用CachedUidGenerator 对应Spring配置分别为: [default-uid-spring.xml](https://github.com/baidu/uid-generator/blob/master/src/test/resources/uid/default-uid-spring.xml)、[cached-uid-spring.xml](https://github.com/baidu/uid-generator/blob/master/src/test/resources/uid/cached-uid-spring.xml) #### CachedUidGenerator配置 项目资源包路径下创建`uid`文件夹,然后到官方`uid-generator` `测试` [注意:`这里是测试资源包`] 资源包路径下`uid/cached-uid-spring.xml` 复制`cached-uid-spring.xml`文件,粘贴到该文件夹`uid`内。 ```xml ``` ### 创建配置UidConfig ```java package com.qfjy.config; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; /** * @ClassName UidConfig * @Description TODO * @Author guoweixin * @Version 1.0 */ @Configuration //导入外部XML配置文件 @ImportResource(locations = { "classpath:uid/cached-uid-spring.xml" }) public class UidConfig { } ``` ### 入口类 ```java @SpringBootApplication @MapperScan(basePackages = {"com.baidu.fsg.uid"}) /("com.baidu.fsg.uid")扫描到工具类Mapper类 public class BootDistributedIdApplication { public static void main(String[] args) { SpringApplication.run(BootDistributedIdApplication.class, args); } } ``` ### 测试 ```bat @SpringBootTest @Slf4j class BootDistributedIdApplicationTests { @Resource(name="cachedUidGenerator") private UidGenerator uidGenerator; @Test void contextLoads() { log.info("开始--->"); System.out.println(uidGenerator.getUID()); log.info("----->结束---->"); } } ``` ![输入图片说明](https://images.gitee.com/uploads/images/2021/0815/230859_536eb267_720177.png "4.png") # 方案总结 ​ 实际业务中,除了分布式ID全局唯一之外,还有是否趋势/连续递增的要求。根据具体业务需求的不同,有两种可选方案。 ​ 一是只保证全局唯一,不保证连续递增。二是既保证全局唯一,又保证连续递增。