温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Redis中怎么提高分布式锁的可用性

发布时间:2021-08-10 15:29:39 来源:亿速云 阅读:98 作者:Leah 栏目:大数据

Redis中怎么提高分布式锁的可用性,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

Redis分布式锁简介

redis给我们提供了分布式锁,开启锁的指令是setnx(set if not exists),释放锁指令del,下面我们来尝试

> setnx lookname mango(integer) 1> get lookname"mango"> del lookname(integer) 1> get mango(nil)
死锁

这里我们思考一个问题,如果我们在执行逻辑的时候出现异常了,那么这个锁就会一直得不到释放,导致死锁,所以我们想办法让它自己释放,添加一个过期时间这个指令是expire key seconds,即使我们不del,他它过了这个时间会自动释放

> setnx lookname mango(integer) 1> expire lookname 5(integer) 1> get lookname(nil)

还有一个问题,如果我在执行setnx和expire的过程中出现了异常怎么办?我们很快想到了用事务,但是我们这里注意expire依赖setnx,expire这个是当setnx抢到了资源的时候我们的expire才会执行,否则是执行不成功的,事务里面没有if else语句。

为了解决这个问题,redis开源社区开发出很多分布式锁的lib库,也就是说我们每次使用分布式锁的时候都要引入这个第三方的库,关于这个问题作者在Redis2.8版本中加入了set扩展,把这两个命令放在一起执行。

> set lookname mango ex 5 nxOK> get lookname"mango"> get lookname    # 5s 后(nil)
超时问题  

如果我们在加锁后到这个锁被释放的时间内的业务逻辑还没有执行完,那么这个时候出现了新的问题就是超时,比如说我只想的逻辑需要30秒,而我的锁过期时间只有10秒,此时我的逻辑还没有处理完,问题就来了。

不使用过期时间

解决超时问题的快捷办法就是不使用过期时间,我们需要在key后面添加一个比较隐私的随机数,例如name1564835、name6879425,达到减少key的碰撞,我们对这个key做上标记,等执行逻辑处理完后程序回收这个内存。

延迟回收

如果10秒钟不够那么我们可以给这个key延长回收时间,我们在key回收前判断客户端是否还在使用这个key,如果没有使用这个key我们就什么都不做,如果在使用,我们就增加回收时长,如何做?我们可以在调用端重开一个线程,监测快过期的key,客户端可以给redis服务实例发送一个Lua脚本检测这个key的值有没有改变,如果没有改变让redis服务端延长锁的时间。

RedLock算法

我们在一个集群中,当主节点挂掉时,从节点会取而代之,原先第一个客户端在主节点中申请成功了一把锁,但是这把锁还没有来得及同步到从节点,主节点突然挂掉了,然后从节点变成了主节点这个新的节点内部没有这个锁,所以当另一个客户端过来请求加锁时,此时两个客户端都持有这个资源,问题又出现了。

但是这个问题是极小概率事件并且是非常短时间造成的,从分布式系统角度上我们是可以容忍这个问题的。但是我们希望redis完全不受影响,可以考虑 redlock。Redlock算法是由Antirez发明的,它的流程比较复杂,不过已经有了很多开源的 library 做了良好的封装,用户可以拿来即用,比如 redlock-py。

redlock.Redlock()

RedLock算法原理:

1.获取当前时间(单位是毫秒)。

2.轮流用相同的key和随机值在N个节点上请求锁,在这一步里,客户端在每个master上请求锁时,会有一个和总的锁释放时间相比小的多的超时时间。比如如果锁自动释放时间是10秒钟,那每个节点锁请求的超时时间可能是5-50毫秒的范围,这个可以防止一个客户端在某个宕掉的master节点上阻塞过长时间,如果一个master节点不可用了,我们应该尽快尝试下一个master节点。

3.客户端计算第二步中获取锁所花的时间,只有当客户端在大多数master节点上成功获取了锁((N/2) +1),而且总共消耗的时间不超过锁释放时间,这个锁就认为是获取成功了。

4.如果锁获取成功了,那现在锁自动释放时间就是最初的锁释放时间减去之前获取锁所消耗的时间。

5.如果锁获取失败了,不管是因为获取成功的锁不超过一半(N/2+1)还是因为总消耗时间超过了锁释放时间,客户端都会到每个master节点上释放锁,即便是那些他认为没有获取成功的锁。

注意:加锁时,它会向过半节点发送 set(key, value, nx=True, ex=xxx) 指令,只要过半节点 set 成功,那就认为加锁成功。释放锁时,需要向所有节点发送 del 指令。不过 Redlock 算法还需要考虑出错重试、时钟漂移等很多细节问题,同时因为 Redlock 需要向多个节点进行读写,意味着相比单实例 Redis性能会下降一些,代码额外引入第三方lib。

关于Redis中怎么提高分布式锁的可用性问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI