全局唯一ID:
全局ID生成器,是一种在分布式系统下用来生成全局唯一ID的工具,一般要满足以下特征:
- 唯一性
- 递增性
- 安全性
- 高可用
- 高性能
全局唯一ID生成策略:
- UUID
- Redis自增
- snowflake算法
- 数据库自增
Rdeis自增ID策略:
我们这里使用redis自增策略:
- 每天一个key,方便统计
- ID构造是 时间戳 + 计数器
代码实现
@Component
public class RedisIdWorker {
/**
* 开始时间戳
*/
private static final long BEGIN_TIMESTAMP = 1640995200L;
/**
* 序列号的位数
*/
private static final int COUNT_BITS = 32;
@Resource
private StringRedisTemplate stringRedisTemplate;
public long nextId(String keyPrefix) {
// 1.生成时间戳
LocalDateTime now = LocalDateTime.now();
long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
long timestamp = nowSecond - BEGIN_TIMESTAMP;
// 2.生成序列号
// 2.1获取当前日期,精确到天
String data = now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
long count = stringRedisTemplate.opsForValue().increment("id:" + keyPrefix + ":" + data);
// 3.拼接并返回
return timestamp << COUNT_BITS | count;
}
}
测试
使用Springboot测试
//注解注入工具类
@Resource
private RedisIdWorker redisIdWorker;
//线程池测试
private final ExecutorService es = Executors.newFixedThreadPool(1000);
@Test
public void testRedisIdWorker() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(300);
//实现Runnable接口定义线程任务
Runnable task = () -> {
for (int i = 0; i < 100; i++) {
long id = redisIdWorker.nextId("test");
//System.out.println("id==>" + id);
}
latch.countDown();
};
long begin = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
es.submit(task);
}
latch.await();
long end = System.currentTimeMillis();
Thread.sleep(2000);
System.out.println("time=================" + (end - begin));
}