Redis 并发锁实现

5 篇文章 0 订阅
2 篇文章 0 订阅

听到Redis 实现并发锁,大家应该都很熟悉了,不知道有多少同学踩过redis并发锁的坑。

最近项目中有同学实现了并发锁,通过代码review还是发现有些同学理解的并不深入,为后续的运行埋下来了巨大的隐患,今天空闲之余再重温一下并发锁,希望多刚接触redis 锁的同学有启发。

首先列举一下几种常见的写法啊

1、第一种,也是在review代码时经常遇到的

 

Jedis jedis;

public boolean tryLock(String key){

    String value = jedis.get(key);

    if(org.apache.commons.lang3.StringUtils.isEmpty(value)){

        jedis.set(key,"1");
        jedis.expire(key,1000);

        return true;
    }

    return false;

}
这种写法有几个问题呢?
1 String value = jedis.get(key);   多线程高并发访问时,拿到的value都为空都能拿到锁,并发控制失效
2 jedis.set(key,"1") ;jedis.expire(key,1000); 非原子操作,设置失效时间失败时,其他线程将永远获取不到锁。造成死锁。

2、第二种也是经常遇到的,还是先上代码才有说服力

    

Jedis jedis;

public boolean tryLock(String key){

    long value = jedis.incr(key);
    
    // 已经有其他线程获取到锁
    if(value != 1)
    {
      return false;    
    }else
    {
        jedis.expire(key,100);
        return true;
    }
    

}

这种写法又有什么问题呢?

首先和第一个有相似之处的是,设置redis失效时间不是原子操作,中间任何异常导致设置失效时间出错时,会造成后续的死锁

 

看了这几个,有没有踩过同样的坑呢?

首先我认为写redis 并发锁,有几个坚持的原则

A、key和redis的失效时间是不是原子操作

B、get--》compare的方法在高并发场景写不可取

 

3、三是我们最常用的,能满足我们常规加锁需求

 

Jedis jedis;

// 加锁
public boolean tryLock(String key){

    String result = jedis.setex(key,1000,"1");


    if(StringUtils.equals("OK",result)){

        return true;
    }
 
    return false;
}


// 释放锁
public void  releaseLock(String key){
    
    jedis.del(key);
    
}
这里的实现思路是客户端进来加锁、任务执行完毕后释放锁,看上去这种方式是完美的。但......我们redis 设置都是主备的,
Client A 在master上得到锁,此时redis master Down机,redis将切换到Slave机器,Client B在此时去获取锁,
此时Client A的锁信息还有同步到Slave,这种情况Client A、B 都将获取到并发锁。
对于这种情况大家还是多看看redis 官方对并发锁的实现讲解。java 版本的开源实现并发锁Redisson
注:以上代码均为伪代码,有问题大家可以留言讨论,也希望文章对看到的人有些许用途 

 

 
 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值