先提供我的测试代码
/**
* 领卷接口
* 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() 看门狗机制
- watch dog 在当前节点存活时每10s给分布式锁的key续期 30s;
- watch dog 机制启动,且代码中没有释放锁操作时,watch dog 会不断的给锁续期;
- 从可2得出,如果程序释放锁操作时因为异常没有被执行,那么锁无法被释放,所以释放锁操作一定要放到 finally {} 中;
- 不需要考虑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)
源码分享借鉴小滴课堂高并发大课项目 小滴课堂 - 首页