前情提要
百度的UidGenerator是一个基于Java语言实现的分布式唯一ID生成器,它基于Snowflake算法进行了优化和改进
算法组成部分:
- 1位符号位:由于long类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以这一位固定为0。
- 28位时间戳:从起始时间开始计算的秒值, 能够承受大约8.5年的时间 。
- 22位机器ID:通过实例启动时,对数据库表进行查询,获取实例的机器id,最大可分配 4194303 个id。
- 13位序列号:用于同一毫秒内生成的不同ID,支持每个节点每毫秒产生8192个唯一的ID。
由于算法默认时间范围是28位,仅能表示8.7年左右的时间,且默认的起始时间为 "2016-05-20",
算法默认配置下, 支持最大的时间是 2024-11-20 21:24:16。 当超出改时间,时间部分会越位,进位到符号位,造成生成的ID为负数。
ID出现负值,一般对于业务逻辑影响不大, 主要影响了数据排序,当查询未设置排序条件时,负数id默认排在前面。
但是业务如果有依据ID排序的情况,则可能产生不可预见的问题。另外要确保前端对负数id的处理。
github地址:https://github.com/baidu/uid-generator
相关ISSUE
- #100
- #29
处理方式
- 调整区位大小,增加时间区位大小,彻底解决时间超限问题,需要根据业务系统时间情况考虑:
- 启用新的wokerid,不可与分配过的id重复, 设置启动时间为当前日期
@Bean("cachedUidGenerator")
CachedUidGenerator getCachedUidGenerator(DisposableWorkerIdAssigner disposableWorkerIdAssigner){
CachedUidGenerator cachedUidGenerator = new CachedUidGenerator();
cachedUidGenerator.setWorkerIdAssigner(disposableWorkerIdAssigner);
// setting generator Bits config......
cachedUidGenerator.setTimeBits(23);
cachedUidGenerator.setWorkerBits(31);
cachedUidGenerator.setSeqBits(9);
cachedUidGenerator.setEpochStr("2024-10-24");
return cachedUidGenerator;
}
推荐参数:
protected int timeBits = 31;
protected int workerBits = 23;
protected int seqBits = 9;