Redis实现全局唯一id

ID是一个唯一标识,在业务开发中,我们要保证ID是唯一的,不容易猜测的。

在数据库中,对于mybatis-plus,它自带了雪花算法生成id的工具包来为我们使用,并生成唯一id

雪花算法的生成策略是这样的:

 采用一个64位bit long型来生成唯一id

那我们如果没用导入这样一个工具包,让我们自己写的话,我们又如何保证唯一性呢?保证他的可用性呢?保证它的不可猜测性呢?

有人会说,用自增啊!这样每次都+1每个数据的id肯定是不一样的。这样好像说的对,但是这样如果数据量一大,你用long型,最多也就2^64个不一样的数,平常可能够用,但对大项目来说,这显然有点不够了,同时,这种数又容易被猜测,知道了一个,下一个也就知道了,不安全,所以,这种方案适合小业务,同时又不是很重要的业务来使用。

既然我们不导这样的工具包,那我们自己写一个这样的工具包,总可以吧!

由于机器码服务码这些有点难搞,那我们就用时间戳和自增数拼接成一个唯一id。

时间总是不一样的,id也是不一样的。这样就拼接好了一个唯一id。

这时有人就说了,那自增也会用完啊!这时,我们可以用redis自增,然后每天用的key不同(拼接日期),这样,一天的业务量肯定是够的。

 好有了思路,我们开始设计具体步骤:

1.获取时间戳

设置初始时间,然后每天时间-初始时间,得到时间戳

2.生成序列号

通过标识+日期得到key,然后拿到自增数

3.拼接

通过位运算,将时间戳左移32位,然后或运算拼接

@Component
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) {
        // 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;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值