使用RedisAtomicLong和StringRedisTemplate生成递增原子序列号及其保证原子性的原理

使用RedisAtomicLong和StringRedisTemplate生成递增原子序列号及其保证原子性的原理

1. 参考链接

2. 为什么要使用redis生成原子序列号,而不是用java自带的atomic包一样进行原子性操作

  1. AtomicLong只能在一个应用中使用;
  2. RedisAtomicLong可以在所有与Redis有连接的应用中使用;

3. 为什么能够保证原子性

  1. RedisAtomicLong的getAndIncrement使用的是redis的incrBy命令。
  2. redis后台服务是串行的单线程执行,不存在并发,即多线程调用Incr/incrby方法,在redis服务器上仍然是串行的单线程执行,不存在并发,所以这俩命令都是原子自增、线程安全的。
  3. Redis Incrby 命令将 key 中储存的数字加上指定的增量值;Redis Incr 命令将 key 中储存的数字值增1;

4. 实现代码


    @Autowired
    StringRedisTemplate redis;

    String taskNoKey = "20240706";
    // 使用redis原子流水号
    long num = this.incr(taskNoKey, redis.getConnectionFactory()) + 1;

    /**
     * redis流水号自增
     * 
     * @param key      自己设置,保存当前自增值
     * @param liveTime 在redis中的缓存时间,方法中设置单位(秒/分/天……)
     * @return
     */
    // 接受两个参数,key(用于在Redis中存储自增值的键)和RedisConnectionFactory(用于创建Redis连接的工厂)。
    public static Long incr(String key, RedisConnectionFactory redisConnectionFactory) {
        // RedisAtomicLong创建了一个原子长整型变量,其键为key,连接工厂为redisConnectionFactory
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisConnectionFactory);
        // 使用getAndIncrement()方法获取当前自增值,并将其递增。这个方法是原子操作,保证在多线程环境下的安全性。初始值为0;
        Long increment = entityIdCounter.getAndIncrement();
    // 如果increment为null或者等于0,这意味着Redis中没有存储该key的值,或者值已经被重置。在这种情况下,代码将设置该key的过期时间为1天。
        if ((null == increment || increment.longValue() == 0)) {
            entityIdCounter.expire(1, TimeUnit.DAYS); // 设置自增值过期时间,liveTime 过期时间;TimeUnit.DAYS
        }
        if (increment > 9999) {
        //    待处理
        }
        return increment;
    }
  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值