分布式锁redisson思考总结

先提供我的测试代码

    /**
     * 领卷接口
     *  1.获取优惠劵是否存在
     ** 2.校验优惠劵是否可以领取 时间 库存 超过限制
     * 3 扣减库存
     * 4 报错领卷记录
     * @param couponId
     * @param category
     * @return
     */
    @Override
    public JsonData addCoupon(long couponId, CouponCategoryEnum category) {

        LoginUser loginUser = LoginInterceptor.threadLocal.get();

        String lockKey = "lock:coupon:"+couponId;
        RLock rLock = redissonClient.getLock((lockKey));
        //多个线程进入,会阻塞等待释放锁
        rLock.lock();
        log.info("领卷接口加锁成功:{}",Thread.currentThread().getId());

            try{
                CouponDO couponDO= couponMapper.selectOne(new QueryWrapper<CouponDO>().eq("id",couponId)
                        .eq("category",category.name()));
                //优惠劵是否可以领取
                this.checkCoupon(couponDO,loginUser.getId());
                //构建领卷记录
                CouponRecordDO couponRecordDO = new CouponRecordDO();
                BeanUtils.copyProperties(couponDO,couponRecordDO);
                couponRecordDO.setCreateTime(new Date());
                couponRecordDO.setUseState(CouponStateEnum.NEW.name());
                couponRecordDO.setUserId(loginUser.getId());
                couponRecordDO.setUserName(loginUser.getName());
                couponRecordDO.setCouponId(couponId);
                couponRecordDO.setId(null);
                //扣减库存
                int rows =couponMapper.reduceStock(couponId);
                if(rows == 1){
                    //库存扣减成功才保存记录
                    couponRecordMapper.insert(couponRecordDO);
                }else {
                    log.warn("发放优惠劵失败:{},用户:{}",couponDO,loginUser);
                    throw new BizException(BizCodeEnum.COUPON_NO_STOCK);
                }
            }finally {
                rLock.unlock();
                log.info("解锁成功");
            }
        return JsonData.buildSuccess();
    }

这里仅仅介绍lock()  和 lock(TimeUint)

思考

这个redisson分布式锁,如果这样无线续期的话,怎么办?就是server端卡顿,最终也是死锁吗

这个你要看业务场景,也可以配置最大超时间 

lock()    看门狗机制

  1. watch dog 在当前节点存活时每10s给分布式锁的key续期 30s;
  2. watch dog 机制启动,且代码中没有释放锁操作时,watch dog 会不断的给锁续期;
  3. 从可2得出,如果程序释放锁操作时因为异常没有被执行,那么锁无法被释放,所以释放锁操作一定要放到 finally {} 中;
  4. 不需要考虑watch dog 机制中,finally{}unlock失败,导致无线延期导致死锁,因为无论释放锁操作是否成功,EXPIRATION_RENEWAL_MAP中的目标 ExpirationEntry 对象已经被移除了,watch dog 通过判断后就不会继续给锁续期了

总结

重载方法lock()指定时间,(加个时间参数),然后fianlly{}中的unlock解决的是原生分布式锁中判断和删除不一致导致的误删除key;


不加参数lock()锁,watch dog机制的话本身就不会出现误删的操作,但有阻塞的风险,可以添加最大超时时间解决,finally{}unlock()两种都需要添加,可以在业务完成的时候unlock,效率更高
不需要考虑watch dog 机制中,finally{}unlock失败,导致无线延期导致死锁,因为无论释放锁操作是否成功,EXPIRATION_RENEWAL_MAP中的目标 ExpirationEntry 对象已经被移除了,watch dog 通过判断后就不会继续给锁续期了。但是仍需要注意业务层阻塞的情况,也就是说,如果一个拿到锁的线程一直没有完成逻辑,那么watch dog会帮助线程不断的延长锁超时时间,锁不会因为超时而被释放。这里可以配置最大超时时间解决

引用借鉴

Redisson 分布式锁实战与 watch dog 机制解读 - 上帝爱吃苹果-Soochow - 博客园 (cnblogs.com)

源码分享借鉴小滴课堂高并发大课项目 小滴课堂 - 首页

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值