美文网首页微服务
使用redis生成分布式全局唯一ID

使用redis生成分布式全局唯一ID

作者: 生不悔改 | 来源:发表于2022-04-16 02:37 被阅读0次

背景

分布式系统中由于跨进程跨系统,在某些场景中,我们需要生成全局的唯一ID,例如订单系统,并发情况下,不同的系统需要同时生成不一样的订单ID方便后续的订单下单与查询等等。

解决

网上有很多解决方法,例如:雪花算法,薄雾算法,利用单台数据库生成唯一主键方法,以及redis生成唯一ID方法,等等

redis生成全局唯一ID的原理

我们生成的订单号一般需要存在Long类型中,正好Long类型是64位,所以将第一位永远设置成0,表示正数。后面31位表示时间戳,可以表示的数字为2的31次方(0-2147483648),单位秒,再后面的32位可以表示成2的32次方的订单号(0-4294967296)。这种思想主要是借鉴雪花算法的原理。

全局唯一ID.png
解释
1.符号位:1bit,永远为0,表示正数
2.时间戳:31bit,最大2147483648秒,大概69年
3.序列号:32bit,最大4294967296,表示一秒中内能生成的不同的订单数(接近43亿)
一般一秒中能产生43亿个不一样的订单号,基本满足各种电商场景了。

java代码实现

@Component
public class RedisIdMaker {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 时间戳开始时间,从2022年1月1号0点0时0分开始
     */
    private static final Long START_TIME = 1640995200L;

    /**
     * 订单生成数量  每天最多2的31次方个订单数量
     */
    private static final int COUNT_BITS = 32;

    private static final String ORDER_COUNT_KEY = "order:";


    /**
     * 根据redis生成唯一订单号
     *
     * @return
     */
    public Long generateNextId() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        long currentStamp = now.toEpochSecond(ZoneOffset.UTC);
        // 获取当前时间戳(秒)
        long timeStamp = currentStamp - START_TIME;
        // 组装成key=order:2022:01:01(组装成这种形式方便日后根据日期统计当天的订单数量)
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd:HH:mm"));
        String redisKey = ORDER_COUNT_KEY + date;
        // 订单自增长
        long orderCount = stringRedisTemplate.opsForValue().increment(redisKey);
        // 返回唯一订单号(拼接而来的)
        return timeStamp << COUNT_BITS | orderCount;
    }

    /**
     * 获取2022年1月1号0点0时0分的时间戳
     * @param args
     */
    public static void main(String[] args) {
        LocalDateTime startLocalTime = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
        long startTime = startLocalTime.toEpochSecond(ZoneOffset.UTC);
        System.out.println(startTime);
        LocalDateTime now = LocalDateTime.now();

        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd:HH:mm"));
        System.out.println(date);
    }
}

解释
时间戳开始是从1970年开始的,当31位时间戳全部是0的情况下,那么就是最开始,当当31位时间戳全部是1的情况下那么就是2039年,也就是说只能用到2039年

64位表示2022年1月1号0点0时0分.png
图中后32位表示2022年1月1号0点0时0分的秒时间戳。
timeStamp << COUNT_BITS

这行代码表示将上图中的时间戳往前位移32位,就变成了下面的


左移32位后.png

最后就是这段代码

timeStamp << COUNT_BITS |orderCount

| 是把某两个数中, 只要其中一个的某一位为1,则结果的该位就为1。
由于我们现在表示成二进制,只有0和1,所以这样运算后变成了


第一笔订单.png

测试

 @Test
 public void test() throws InterruptedException {
        System.out.println(redisIdMaker.generateNextId());
    }

结果

39001021761978369

进制转换


image.png

批量生成测试

 @Test
 public  void contextLoads() throws InterruptedException {

        CountDownLatch countDownLatch = new CountDownLatch(300);
        // 定义任务
        Runnable task = ()->{
            for (int i = 0; i < 100; i++) {
                long id = redisIdMaker.generateNextId();
                System.out.println(id);
            }
            countDownLatch.countDown();
        };
        for (int i = 0; i < 300; i++) {
            es.submit(task);
        }
        countDownLatch.await();
    }

结果:控制台一共生成了30000条ID


image.png

在看我们的redis,同样记录了,这一秒中生成的订单号数是30000

image.png

总结

利用redis生成全局唯一ID,其实redis扮演的角色就是一个计数器的作用,方便后续的统计。
优点:高性能,高并发,唯一性,递增性,安全性。
缺点:需要依赖redis去实现

相关文章

  • Redis-全局唯一ID

    零、本文纲要 一、全局唯一ID 二、Redis生成全局唯一ID1、snowflake算法全局唯一ID策略2、Red...

  • 分布式唯一Id(雪花算法),原理+对比+方案

    集群高并发情况下如何保证分布式唯一全局Id生成 为什么需要分布式全局唯一Id,以及分布式Id的业务需求 在复杂分布...

  • 使用redis生成分布式全局唯一ID

    背景 分布式系统中由于跨进程跨系统,在某些场景中,我们需要生成全局的唯一ID,例如订单系统,并发情况下,不同的系统...

  • 分布式系统中生成全局唯一ID方案

    本文主要介绍在一个分布式系统中, 如何去生成全局唯一的 ID。 前言 单纯的生成全局ID并不是什么难题,生成全局的...

  • 分布式、高并发下ID生成 - Redis

    1. 分布式、高并发下ID生成要求 全局唯一 趋势递增 效率高(生成、使用、索引) 控制并发 2. 策略一:UUI...

  • 04.分布式系统的id生成方式

    分布式ID需要满足那些条件? 全局唯一:必须保证ID是全局性唯一的,基本要求高性能:高可用低延时,ID生成响应要块...

  • UUID

    IdWorker.java 高并发分布式系统中生成全局唯一Id汇总 Twitter的分布式自增ID算法snowf...

  • 数据库 ID 生成方案:Redis

    使用 Redis 来生成分布式 ID,其实和利用 Mysql 自增 ID 类似,可以利用 Redis 中的 inc...

  • 如何生成全局唯一id

    为什么需要全局唯一id 在分布式架构下,经常有需求需要生成全局唯一id,比如优惠券等券码,或者分库分表,每个表都用...

  • 高并发下如何生成唯一ID

    通过本文档你将学习到 为什么需要分布式全局唯一ID以及分布式ID的业务需求 ? ID生成规则部分硬性要求?目标出现...

网友评论

    本文标题:使用redis生成分布式全局唯一ID

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