赞
踩
在分布式系统中,生成唯一ID是一个常见的需求。传统的数据库自增ID无法满足分布式系统的需求,因为多个节点可能同时生成ID,容易导致冲突。本文将介绍一种使用 Redis 实现分布式唯一ID的方法,并通过代码示例进行讲解。
在电商系统中,每个订单、用户等都需要一个唯一的标识符。这些标识符不仅需要全局唯一,还要能够快速生成。因此,我们需要一个高效、可靠的方法来生成唯一ID。
我们可以结合时间戳和自增序列来生成唯一ID。具体方案如下:
最终生成的ID格式如下:
ID = 时间戳 << 序列号位数 | 序列号
下面是具体的代码实现:
- @Component
- public class RedisIdWorker {
- private static final long BEGIN_TIMESTAMP = 1704067200L;
- private static final int COUNT_BITS = 32;
-
- private StringRedisTemplate stringRedisTemplate;
-
- public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
- this.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 date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
- // 2.2自增长
- Long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);
-
- // 3.拼接并返回
- return timestamp << COUNT_BITS | count;
- }
- }
在这段代码中:
LocalDateTime.now().toEpochSecond(ZoneOffset.UTC)
获取当前时间戳,并减去一个起始时间戳(BEGIN_TIMESTAMP),得到相对时间戳。increment
方法实现每日的自增序列,保证在同一天内的ID是唯一的。为了验证我们的ID生成器是否能高效、正确地生成ID,我们可以编写以下测试代码:
- @Resource
- private RedisIdWorker redisIdWorker;
-
- private ExecutorService es = 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++) {
- es.submit(task);
- }
- latch.await();
- long end = System.currentTimeMillis();
- System.out.println("耗时:" + (end - begin) + "ms");
- }
在这段代码中,我们使用线程池并发生成ID,并统计生成时间,验证生成ID的效率。
通过使用 Redis,我们可以高效地生成分布式唯一ID。该方法结合了时间戳和 Redis 的自增特性,保证了ID的有序性和唯一性。同时,Redis 的高性能也保证了ID生成的效率。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。