全局唯一ID
为什么要自己生成全局唯一ID
在特殊情况下,如果使用主键自增,id太过于规律,容易被别人发现额外的信息,我们在设置id的时候需要考虑唯一性,安全性(不规律),可靠性(唯一),递增性(递增有利于创建索引)。
如何生成全局唯一ID
生成全局唯一ID的方式有很多种,这里介绍使用redis自增生成全局唯一ID。
不直接使用redis主键自增,在原来的基础上添加其他的信息。
采用数值类型。
id的组成部分:
-
符号位:1bit,表示正数永远为0
-
时间戳:31bit,以秒为单位,可以使用69年
-
序列号:32bit,秒内计数器,每秒可以产生2^32次方个不同id
工具类
/**
* @ClassName: RedisIdWorker
* @Description: 全局唯一ID生成器
* @Author: csh
* @Date: 2025-02-18 17:45
*/
@Component
public class RedisIdWorker {
// 开始时间戳
private static final long BEGIN_TIMESTAMP = 1735689600;
// 序列号位数
private static final long COUNT_BITS = 32;
@Autowired
private StringRedisTemplate stringRedisTemplate;
public long nextId(String keyPrefix){
// 生成时间戳
LocalDateTime now = LocalDateTime.now();
long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
long timestamp = nowSecond - BEGIN_TIMESTAMP;
// 生成序列号
String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);
// 返回
return timestamp << COUNT_BITS | count;
}
}