Redis分布式锁

一:redis常见的用途

1 缓存

2 计数器

3 排行榜

4 分布式锁

二:redis实现分布式锁

分布式锁主要有以下几个问题:

1 互斥性:多个机器不能同时获得锁,同一时刻只有一台机器占有锁

2 安全性:保证加锁和解锁都是同一台机器,不能误释放别人的锁

3 死锁:节点故障,但是一直占有锁未释放,其他节点一直加锁失败

4 容错:一个节点故障,保证其他节点可以释放和获取到锁

三:主要用到的redis命令

1:setnx key value  key不存在时 赋值 然后返回1  key存在时 返回0

有一个问题就是,如果线程1 获取锁之后  在释放锁之前挂掉了,锁一直没有释放其他线程就没法获取说那么这就死锁了,所以一定要设置一个过期时间。赋值和设置过期时间是2个操作,必须要保证原子性。。下边命令能满足

SET key value [EX seconds] [PX milliseconds] [NX|XX]

2:在释放锁时我们很多时候会直接del key,但是这样是不安全的,可能会释放不该释放的锁

所以我们在释放锁的时候 要验证一下 是不是自己锁的,是自己锁的那么就释放,不是自己锁的 就不该自己释放

总结一下就是:拿到锁之后 要设置过期时间,释放锁的时候 要判断一下

对于锁的过期时间:设置要合理,不能过长也不能过短,过长影响新的线程重新获得锁的流程,影响业务响应时间。太短导致业务未执行完,锁自动释放,另一个线程获得锁,重新开始执行逻辑,这就间接要求业务保证幂等性,非幂等性的业务会影响数据一致性。针对这种情况解决方案:守护线程为锁延长过期时间。

对于释放锁判断问题:判断redis里边的key-value value值是不是当前线程设置的,就要先从redis取出来 然后比较  相等才能删除。取值--->删除  这是2步操作,不是原子操作,存在判断后锁过期,另一个线程获得锁,然后误释放锁的情况。针对这种情况,可以使用lua脚本。

luaScript = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end"

四:上代码

 

self.tryLock(self.lockFunc,10)

self.unlock(["helloworld"],["123456"])

上面描述的是单点情况,若在redis集群环境依然存在问题:
由于Redis集群数据同步为异步,假设在Master节点获取到锁后未完成数据同步情况下Master节点crash,此时在新的Master节点依然可以获取锁,所以多个Client同时获取到了锁。
解决方案:
redlock算法,set向多半节点发送命令,过半节点成功即为成功,释放时想全部节点发送。

附带一篇 redis调用lua

https://www.cnblogs.com/-wenli/p/13262877.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值