基于Redis实现分布式锁的几种坑你是否踩过《下》

DBC 1.6K 0
存在什么问题?

多个命令之间不是原子性操作,如setnx和expire之间,如果setnx成功,但是expire失败,且宕机了,则这个资源就是死锁

基于Redis实现分布式锁的几种坑你是否踩过《下》插图

使用原子命令:设置和配置过期时间  setnx / setex
如: set key 1 ex 30 nx
java里面 redisTemplate.opsForValue().setIfAbsent("seckill_1",1,30,TimeUnit.MILLISECONDS)

第二个坑:业务超时,存在其他线程勿删,key 30秒过期,假如线程A执行很慢超过30秒,则key就被释放了,其他线程B就得到了锁,这个时候线程A执行完成,而B还没执行完成,结果就是线程A删除了线程B加的锁

基于Redis实现分布式锁的几种坑你是否踩过《下》插图2

可以在 del 释放锁之前做一个判断,验证当前的锁是不是自己加的锁, 那 value 应该是存当前线程的标识或者uuid
​
String key = "coupon_66"
String value = Thread.currentThread().getId()
​
if(setnx(key,value) == 1){
    expire(key,30,TimeUnit.MILLISECONDS)
    try {
        //做对应的业务逻辑
    } finally {
      //删除锁,判断是否是当前线程加的
      if(get(key).equals(value)){
          //还存在时间间隔
          del(key)
        }
    }
}else{
  
  //睡眠100毫秒,然后自旋调用本方法
​
}
温馨提示

进一步细化误删

当线程A获取到正常值时,返回带代码中判断期间锁过期了,线程B刚好重新设置了新值,线程A那边有判断value是自己的标识,然后调用del方法,结果就是删除了新设置的线程B的值
核心还是判断和删除命令 不是原子性操作导致

那如何解决呢?继续看小编文章!

发表评论 取消回复
表情 图片 链接 代码

分享