# sequence
**Repository Path**: sections/sequence
## Basic Information
- **Project Name**: sequence
- **Description**: sequence是一个基于数据库实现的分布式全局序列号生成器,适用于分布式场景下需要连续递增或递减序号的场景
- **Primary Language**: Java
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 4
- **Forks**: 3
- **Created**: 2022-12-27
- **Last Updated**: 2024-10-05
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 1 简介
sequence是一款轻量的分布式序列号生成器
基于数据库实现的分布式全局序列生成,适用于分布式场景下需要连续递增或递减序号的场景,具备以下特点:
- 简单轻量
- 开箱即用
- 可扩展性强
# 2 主要概念
- 序列号:从小到大或从大到小逐渐递增或递减的数字序列,可以用于数据库表ID,业务编号等场景
- 序列号Key:序列号的唯一标识
- 序列号初始值:序列号默认从0开始,也可以指定初始值为任何其他值
- 序列号步长:序列号默认自动增步长为1,也可以指定为负数,负数步长可以实现从大到小的序列
- 序列号缓存:为了提升序列号获取性能,可以使用序列号缓存机制,缓存值必须大于0:
* 当缓存值为1时,每次从数据库获取1个ID,相当于没有缓存
* 当缓存值大于1时,每次从数据库获取多个ID并缓存到本地内存中,后续优先从缓存中获取ID
- 默认序列号:系统内置了一个默认序列号,key为default,初始值为0,步长为1,缓存大小为50,可以开箱即用
- 自定义序列号:用于可以定义自己的序列号,为不同key的序列号设置不同的初始值、步长和缓存大小
- 跳号:序列号一旦生成后,如果业务异常没有使用,或者服务器重启缓存丢失,都会导致跳号现象产生
* 如果业务没有严格要求序号必须连续可以忽略
* 如果业务要序号求必须连续可以配置缓存为1或者使用Redis缓存
# 3 快速开始
## 3.1 引入
基于springboot的应用可以使用下面的starter引入sequence组件
```xml
io.gitee.sections
sequence-spring-boot-starter
版本
```
## 3.2 建表
建表SQL参考sequence-core包中的script目录下的create_table.sql
```sql
CREATE TABLE `SEQ_SEQUENCE` (
`KEY` CHAR(255) NOT NULL PRIMARY KEY COMMENT '序列号标识',
`INITIAL` INT NOT NULL COMMENT '序列初始值',
`STEP_SIZE` INT NOT NULL COMMENT '序列步长大小',
`CACHE_SIZE` INT NOT NULL COMMENT '序列缓存大小',
`CACHE_MODE` CHAR(255) NOT NULL COMMENT '序列缓存模式',
`NUMBER` BIGINT NOT NULL DEFAULT 0 COMMENT '序列号当前最新值'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='序列号生成器记录表'
```
## 3.3 注入
sequence组件中已经声明了SequenceGenerator的Bean,可以直接注入使用
```java
@Autowired
private SequenceGenerator sequenceGenerator;
```
## 3.4 使用
调用next方法获取默认序列的下一个序列号
```java
Long id = sequenceGenerator.next();
```
# 4 自定义序列
sequence组件支持创建多个独立的序列,每个序列可以单独配置初始值、步长和缓存池大小,你需要为每个序列指定一个key作为唯一标识;
组件自动初始化了一个默认序列,默认序列的key为default,初始值为0,步长为1,缓冲池大小为50;
SequenceGenerator接口有两个next方法,分别用于获取默认序列的值或指定序列的值:
```java
public interface SequenceGenerator {
//获取默认序列的下一个值
Long next();
//获取指定序列的下一个值
Long next(String key);
}
```
## 4.1 使用默认参数
调用带参数key的next方法获取下一个序列号,指定序列的key,若该key不存在,则会自定创建一个对应的序列。自动创建的序列的初始值、步长和缓存大小与默认序列参数相同
```java
Long id = sequenceGenerator.next("mySequence");
```
可以通过如下的yml配置修改默认序列的参数
```yaml
sequence:
config:
sequences:
- key: defalt
initial: 0 #初始值
step-size: 1 #步长
cache-size: 50 #缓存池大小
```
## 4.2 使用自定义参数
### 基于YML配置
如果不想使用默认参数创建序列,可以通过如下的yml配置,为指定key的序列的配置单独的初始值、步长和缓存大小
```yaml
sequence:
config:
sequences:
- key: mySequence1
initial: 100
step-size: 1
cache-size: 100
- key: mySequence2
initial: 0
step-size: -1
cache-size: 10
```
然后再使用下面的代码可以获取对应配置的序列号值,对应的序列号将基于yml配置中的参数来初始化
```java
Long id1 = sequenceGenerator.next("mySequence1");
Long id2 = sequenceGenerator.next("mySequence2");
```
### 基于数据库配置
yml中的配置在程序启动后会记录到数据库中,因此也可以在数据库中直接配置或修改对应的key和序列参数,yml配置的优先级高于数据库配置
|KYE|INITAIL|STEP_SIZE|CACHE_SIZE|CAHCE_MODE|NUMBER|
|---|---|---|---|---|---|
|default|0|1|50|inMemory|0|
|mySequence1|100|1|100|inMemory|100|
|mySequence2|0|-1|10|inMemory|-20|
# 5 使用Redis缓存
squence组件默认使用本地内存缓存模式,在分布式环境下,不同节点各自缓存并生成id,会打破序列的严格递增性,最终呈现趋势递增,且服务重启时会存在跳号的问题
如果业务不能接受跳号的情况或必须要求严格递增,可以采用Redis缓存来实现,步骤如下:
第一步:需要引入SpringDataRedis并配置好redis链接信息即可,sequence组件会自动检测RedisTemplate