package org.utils;
import org.junit.jupiter.api.Test;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author ClownMing
* Redis实现全局唯一id
*/
@Component
@SuppressWarnings({"all"})
public class RedisIdWorker {
/**
* 开始时间戳
*/
private static final long BEGIN_TIMESTAMP = 1640995200L;
/**
* 序列号的位数
*/
private static final int COUNT_BITS = 32;
private StringRedisTemplate stringRedisTemplate;
public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
public long nextId(String keyPrefix){ // 这个key 可以看做是业务key,不同的业务对应不同的key
// 1. 生成时间戳
long timeStamp = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) - BEGIN_TIMESTAMP;
// 2. 生成序列号
// 2.1 获取当前日期,精确到天
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
// 2.2 自增长
// 这里即便没有对应的key,redis也会自动帮我们创建
long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date,1);
// 3. 拼接并返回
return timeStamp << COUNT_BITS | count;
}
public static void main(String[] args) {
LocalDateTime time = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
long second = time.toEpochSecond(ZoneOffset.UTC);
System.out.println("second = " + second);
}
@Resource
private RedisIdWorker redisIdWorker;
@Test
void testRedisIdWorker() throws InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(10);
CountDownLatch downLatch = new CountDownLatch(200);
Runnable task = () -> {
for (int i = 0; i < 100; i++) {
long id = redisIdWorker.nextId("order");
System.out.println("id = " + id);
}
downLatch.countDown();
};
long begin = System.currentTimeMillis();
for (int i = 0; i < 200; i++) {
es.submit(task);
}
downLatch.await();
long end = System.currentTimeMillis();
System.out.println("总耗时: " + (end - begin));
}
}