美文网首页
Redis-全局唯一ID

Redis-全局唯一ID

作者: 石头耳东 | 来源:发表于2022-03-25 22:46 被阅读0次

    零、本文纲要

    • 一、全局唯一ID
    • 二、Redis生成全局唯一ID
      1、snowflake算法全局唯一ID策略
      2、Redis自增全局唯一ID策略
    • 三、代码实现

    tips:Ctrl + F快速定位所需内容阅读吧。

    一、全局唯一ID

    1、全局唯一ID特点

    • ① 全局唯一性
    • ② 高性能
    • ③ 单调递增
    • ④ 信息安全
    • ⑤ 高可用

    2、全局唯一ID生成策略

    • ① UUID
    • ② Redis自增
    • ③ snowflake算法
    • ④ 数据库自增
    • ⑤ Zookeeper的znode版本生成ID

    二、Redis生成全局唯一ID

    1、snowflake算法全局唯一ID策略

    此处我们参考snowflake算法的ID策略,其具体策略如下:

    ① 1位,固定位;
    ② 41位,用来记录时间戳(毫秒),接近69年;
    ③ 10位,用来记录工作机器id;
    ④ 12位,序列号,用来记录同毫秒内产生的不同id;

    snowflake算法的ID策略.png

    2、Redis自增全局唯一ID策略

    自定义我们自己的Redis自增的ID策略,具体如下:

    ① 1位,固定位;
    ② 31位,用来记录时间戳(秒),接近69年;
    ③ 32位,序列号,用来记录同一秒内产生的不同id;

    Redis自增的ID策略.png

    三、代码实现

    1、获取开始时间戳

    LocalDateTime#of(int year, int month, int dayOfMonth, int hour, int minute, int second)方法,传入自己需要的起始年月日时分秒;

        public static void main(String[] args) {
            LocalDateTime time = LocalDateTime.of(2022,1,1,0,0,0);
            long l = time.toEpochSecond(ZoneOffset.UTC);
            System.out.println(l);
        }
    

    如:2022年1月1日 00点00分00秒,为1640995200L

    2、编写ID生成工具类

    @Component注解,将工具类注册到Spring容器当中,方便使用;
    BEGIN_TIMESTAMP自定义起始的时间戳;
    COUNT_BITS位移量,后续拼接全局唯一ID时使用;

    @Component
    public class RedisIdWorker {
    
        // 开始时间戳
        private static final long BEGIN_TIMESTAMP = 1640995200L;
        // 位移量
        private static final long COUNT_BITS = 32L;
    
        private StringRedisTemplate stringRedisTemplate;
    
        public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
            this.stringRedisTemplate = stringRedisTemplate;
        }
    
        public long nextId(String keyPrefix){...}
    
    }
    

    timestamp获取当前设置起始时间戳的偏移量;
    拼接key,例如:incr:order:20220325;
    位运算拼接全局ID,timestamp << COUNT_BITS | count;

        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 currentDate = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
            //2.2 自增长
            // 拼接的key,例如:incr:order:20220325
            long count = stringRedisTemplate.opsForValue().increment(
                    RedisConstants.INCR_ID
                    + keyPrefix
                    + RedisConstants.SEPARATE
                    + currentDate);
    
            //3. 拼接并返回
            return timestamp << COUNT_BITS | count;
        }
    

    3、测试生成全局唯一ID

    注入RedisIdWorker对象,用于测试;

        @Resource
        private RedisIdWorker redisIdWorker;
    

    编写测试方法:

    ① 使用线程池模拟并发调用,此处简单处理;

        private ExecutorService es = Executors.newFixedThreadPool(500);
    

    ② 使用CountDownLatch控制线程执行;

            CountDownLatch latch = new CountDownLatch(300); //设置300阈值
    
            Runnable task = () -> {
                ...
                latch.countDown();//每次循环结束,latch -1
            };
    
            ... //开始时间
            ... //执行任务
            latch.await();//等待直到 latch 变为 0
            ... //结束时间
    

    完整的测试方法如下:

        @Test
        public 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);
                }
                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("time = " + (end - begin));
        }
    

    四、结尾

    以上即为Redis全局唯一ID的基础内容,感谢阅读。

    相关文章

      网友评论

          本文标题:Redis-全局唯一ID

          本文链接:https://www.haomeiwen.com/subject/lbadjrtx.html