snowflake替换为uid-generator
# snowflake算法
将long的64位分为4部分,时间戳、数据中心id、工作机器id和序列号,位数分配如下:
/**
* <pre>{@code
* +------+-------------+--------------+-----------+-----------+
* | sign | timestamp | datacenterId | machineId | sequence |
* +------+-------------+--------------+-----------+-----------+
* 1bit 41bits 5bits 5bits 12bits
* }</pre>
*/
2
3
4
5
6
7
8
时间戳部分的时间单位一般为毫秒,也就是说1台工作机器1毫秒可产生4096个id(2的12次方)。
# uid-generator
uid-generator
将long的64位分为3部分,时间戳、工作机器id和序列号,位数分配如下:
/**
* <pre>{@code
* +------+----------------------+----------------+-----------+
* | sign | delta seconds | worker node id | sequence |
* +------+----------------------+----------------+-----------+
* 1bit 28bits 22bits 13bits
* }</pre>
* /
2
3
4
5
6
7
8
- delta seconds:相对于时间戳的增量秒数,单位为秒,
28bits
最大可支持约8.7年。 - worker node id:工作机器id,
22bits
最多可支持4194304次id分配。 - sequence:序列号,每秒下的并发序列,
13 bits
可支持每秒8192个并发。
# 替换原因
uid-generator
相对于snowflake
的优势在于:
snowflake
需要手动配置数据中心id和工作机器id,存在运维工作量,有出错风险。
uid-generator
在启动时通过数据库表注册机器id,不需要手动配置,更加方便。
# 替换过程
uid-generator
的delta seconds
部分默认是28bits
,最大可支持约8.7年,实际使用中需要调整更大一些。
可以将worker node id
部分按实际情况缩小,增加delta seconds
部分的位数。
例如将delta seconds
调整为32位,worker node id
调整为18位,则最大可以支持4294967295秒增量,约136年,支持最大262143次机器id分配。
由于之前使用的是snowflake
,需要保证uid-generator
生成的id始终大于之前的snowflake
生成的id。
取一个当前时间snowflake
生成的id,例如1846130381917519918
。将其按uid-generator
的位数分配拆分,得到delta seconds
。
Long uid = 1846130381917519918L;
//取32位到64位的值
Long deltaeconds = uid >> 31;
2
3
得到秒差值,则只需要保证uid-generator
的时间基准与当前时间的秒差值大于得到的秒差值即可。
之前使用snowflake
作为id生成器时,是将snowflake
对象作为spring
的bean
注入到spring
容器中,然后通过@Autowired
注入到需要使用的地方。
@Configuration
@Data
@ConfigurationProperties(prefix = "snowflake")
public class IdGenderConfig {
//数据中心[0,31] 配置文件中不配置就是0
private long datacenterId;
//机器标识[0,31] 配置文件中不配置就是0
private long machineId;
@Bean
public Snowflake getSnowflake(){
return new Snowflake(machineId,datacenterId);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
为了做最小化改动,可以再实现一个snowflake
类,继承原有的snowflake
类,并将生成id的方法替换为uid-generator
的生成id方法。
@Component
public class Snowflake extends cn.hutool.core.lang.Snowflake {
@Autowired
private UidGeneratorUtil uidGeneratorUtil;
@Override
public long nextId() {
return uidGeneratorUtil.getUid();
}
@Override
public String nextIdStr() {
return uidGeneratorUtil.getUidStr();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15