首页 > 编程知识 正文

redis分布式锁使用场景,redis分布式锁使用

时间:2023-05-04 23:04:10 阅读:22445 作者:4722

将Redis锁与场景结合起来需要注意什么? 超时问题怎么解决?1、redis分布式锁的基本实现redis锁定命令:

setnxresource _ name my _ random _ value px 30000命令的作用是仅在此密钥不存在时设置此密钥的值(NX选项的作用),超时时间为30000毫米

保持SETNX值的唯一目的是安全地解除锁定,避免意外删除其他客户端获取的锁定。 例如,一个客户端获取了锁定,在一个操作中被阻止了很长时间,在超时时间后自动解除锁定,然后该客户端实际上试图删除其他客户端获取的锁定。 因此,如果只使用DEL命令,一个客户端可能会删除对另一个客户端的锁定。 通过验证该值,可以确保每个客户端都是以随机字符串’签名的,并且每个锁只能由获得锁的客户端删除。

必须确保原子性,因为必须在解除锁定时验证此值并删除锁定。 redis支持在原子上运行lua脚本,因此可以使用lua脚本实现原子操作。 代码如下。

ifredis.call(get ), keys(1)==argv )1) thenreturnredis.call )、keys(1) ) elsereturn0end3358www此时,第一个线程拥有的锁定已过期,关键

可以看到,锁定操作通常在完成后手动释放。 常见的解决方案是增加锁定超时时间,然后在发生超时并发问题时手动干预以纠正数据。 这也不是完美的剧本。 但是,由于业务逻辑的运行时间无法控制,仍然会发生超时,当前线程的逻辑可能无法运行,其他线程可能会变空。 此外,如果锁定超时时间过长,则保持锁定的客户端停机,解锁取决于redis的超时时间,业务在超时时间内不可用。

基本上,如果在计算期间发现锁定快要超时,则客户端可以向redis服务实例发送Lua脚本,以允许redis服务端延长锁定时间。 此锁的密钥仍然存在,并且其值仅等于客户端设置的值。 客户端只有在无法在过期时间内延长锁定时才需要重新获取锁定。 基本上,这与获取锁定的算法相同。

这是启动另一个线程进行检查的问题。 这个key是否超时,在某个时间还没有释放。

如果锁定超时时间即将到期且逻辑未运行,则延长锁定超时时间的伪代码:

ifredis.call(get ),KEYS[1]==Argv[1]thenredis.call ),keys[1],ex=3000 ) else getDLock ) )//重获取锁第一个客户端在主节点上申请了锁定,但该锁定尚未同步到从节点,主节点突然锁定。 然后,它从一个节点变为主节点,并且这个新节点内部没有此锁定,因此当另一个客户端请求添加锁定时,它立即得到批准。 这将导致系统中的同一锁同时保留在两个客户端上,从而降低安全性。

但这种焦虑主要只发生在发生故障时,持续时间极短,业务系统往往是可接受的。

2、业务逻辑执行时间超出锁的超时限制导致两个客户端同时持有锁的问题如果您在意高可用性,并希望redis完全不受影响,请考虑使用redlock。 Redlock算法由Antirez发明,流程复杂,但已经将许多开源库打包得很好,用户可以像redlock-py一样立即使用。

importredlockaddrs={ ' host ' : ' localhost ',' port': 6379,' db':},{ ' host ' : ' localhost ' { } ' db ' : } ] dlm=red lock.red lock (addrs ) success=DLM.lock 5000 ) if success 3360打印' lock success ' dlm.unlock

完全独立的无主从关系的n个

Redis master节点以保证他们大多数情况下都不会同时宕机,N一般为奇数。一个客户端需要做如下操作来获取锁:

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

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

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

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

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

5、知识扩展

5.1为什么lua脚本结合redis命令可以实现原子性

Redis 提供了非常丰富的指令集,但是用户依然不满足,希望可以自定义扩充若干指令来完成一些特定领域的问题。Redis 为这样的用户场景提供了 lua 脚本支持,用户可以向服务器发送 lua 脚本来执行自定义动作,获取脚本的响应数据。Redis 服务器会单线程原子性执行 lua 脚本,保证 lua 脚本在处理的过程中不会被任意其它请求打断。

5.2 redis 可重入分布式锁

要实现可重入锁,方法很简单,当加锁失败时判断锁的值是不是跟当前线程设置值相同,伪代码如下:

if setnx == 0 if get(key) == my_random_value //重入 else //不可重入else //获取了锁,等价于可重入

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。