全局唯一ID生成策略:
1.UUID
2.Redis自增
3.snowflake算法
4.数据库自增
本文采用Redis自增
package com.hmdp.utils;
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;
@Component
public class RedisIdWorker {
private static final long BEGIN_TIMESTAMP = 1640995200L;
/**
* 序列号的位数
*/
private static final int COUNT_BITS = 23;
private StringRedisTemplate stringRedisTemplate;
public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
public Long nextId(String keyPrefix) {
//1.生成时间戳
LocalDateTime now = LocalDateTime.now();
long second = now.toEpochSecond(ZoneOffset.UTC);
long timestamp = BEGIN_TIMESTAMP - second;
//2.生成序列号
//2.1获取当前日期,精确到天
String data = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
//2.2自增长
long increment = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + data);
//3.拼接并返回
return timestamp << COUNT_BITS | increment;
}
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);
}
}
测试类
package com.hmdp;
import com.hmdp.service.impl.ShopServiceImpl;
import com.hmdp.utils.RedisIdWorker;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@SpringBootTest
class HmDianPingApplicationTests {
@Resource
private RedisIdWorker redisIdWorker;
//建立500个线程池
private ExecutorService ex = Executors.newFixedThreadPool(500);
@Test
void testIdWorker() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(300);
Runnable task = () -> {
for (int i = 0; i < 100; i++) {
Long id = redisIdWorker.nextId("order");
System.out.println("id" + id);
}
latch.countDown();
};
long begin = System.currentTimeMillis();
for (int i = 0; i < 300; i++) {
ex.submit(task);
}
latch.await();
long end = System.currentTimeMillis();
System.out.println("end" + (end - begin));
}
}