Redis之红锁

Redis Redlock是一种分布式锁实现,通过在多个独立的Redis实例上获取锁来提高可靠性。客户端尝试在所有实例中顺序加锁,如果能在大多数(N/2+1)实例上成功并保证总耗时小于锁的有效时间,则认为获取锁成功。在失败时,会尽快释放已获取的锁并进行重试。释放锁时,需在所有实例上解锁,无论是否认为已成功加锁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官方Redlock链接地址:https://redis.io/topics/distlock

下面是关于官网上redlock的介绍

红锁算法

在该算法的分布式版本中,我们假设有N个Redis masters。这些节点是完全独立的,所以我们不使用复制或任何其他隐式协调系统。我们已经描述了如何在单个实例中安全地获取和释放锁。我们想当然地认为,算法将使用这种方法在单个实例中获取和释放锁。在我们的示例中,我们设置了N=5,这是一个合理的值,因此我们需要在不同的计算机或虚拟机上运行5个Redis主机,以确保它们以基本独立的方式失败。

为了获取锁,客户端执行以下操作:

它以毫秒为单位获取当前时间。

它尝试在所有N个实例中顺序获取锁,在所有实例中使用相同的密钥名和随机值。在步骤2中,当在每个实例中设置锁时,客户端使用一个超时,该超时与锁自动释放的总时间相比很小,以便获取它。例如,如果自动释放时间为10秒,则超时时间可能在~5-50毫秒范围内。这可以防止客户端在尝试与已关闭的Redis节点通话时长时间处于阻塞状态:如果某个实例不可用,我们应该尽快尝试与下一个实例通话。

客户端通过从当前时间中减去在步骤1中获得的时间戳来计算获取锁所用的时间。如果且仅当客户端能够在大多数实例(至少3个)中获取锁,并且获取锁所用的总时间小于锁有效时间,则认为已获取锁。

如果获得了锁,其有效时间将被视为初始有效时间减去经过的时间,如步骤3中计算的。

如果客户端由于某种原因(无法锁定N/2+1实例或有效期为负)未能获取锁,它将尝试解锁所有实例(即使是它认为无法锁定的实例)。

算法是异步的吗?

该算法基于这样的假设:虽然进程之间没有同步时钟,但每个进程中的本地时间仍以大致相同的速率流动,与锁的自动释放时间相比,误差很小。这种假设与现实世界中的计算机非常相似:每台计算机都有一个本地时钟,我们通常可以依靠不同的计算机来产生一个很小的时钟漂移。

在这一点上,我们需要更好地指定互斥规则:只有持有锁的客户端在锁有效期内(如步骤3中获得的)终止其工作,减去一些时间(仅几毫秒,以补偿进程之间的时钟漂移),才能保证互斥规则。

有关需要有界时钟漂移的类似系统的更多信息,本文是一篇有趣的参考文献:RELATIES:一种有效的分布式文件缓存一致性容错机制。

失败后重试

当一个客户端无法获取锁时,它应该在随机延迟后重试,以便尝试取消多个试图同时获取同一资源锁的客户端的同步(这可能会导致无人获胜的分裂状态)。此外,在大多数Redis实例中,客户端尝试获取锁的速度越快,大脑分裂情况的窗口就越小(并且需要重试),因此理想情况下,客户端应该尝试使用多路复用同时向N个实例发送SET命令。

值得强调的是,对于未能获得大部分锁的客户来说,尽快释放(部分)获得的锁是多么重要,这样就不需要等待密钥到期才能再次获取锁(但是,如果发生网络分区,并且客户端不再能够与Redis实例通信,则在等待密钥到期时需要支付可用性罚款)。

释放锁

释放锁很简单,只需要在所有实例中释放锁,不管客户机是否认为自己能够成功锁定给定实例。

 简单总结一下就是:

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

2有效的避免了获取redis发生down机或超时造成的阻塞状态,我们设置获取锁的尝试时间远远小于锁的超时时间,当reids不可用时立刻与下一个redis进行通信。

3对集群的每个节点进行加锁,如果大多数(N/2+1)加锁成功了,则认为获取锁成功。

4如果锁获取成功了,锁的超时时间就是最初的锁超时时间减去获取锁的总耗时时间

5如果锁获取失败了,去尽快释放(部分)获得的锁

### Redis 分布式实现方案——算法 #### 算法概述 (RedLock)算法是由Redis官方提出的一种用于在分布式系统中实现分布式的机制[^1]。该算法通过在多个独立的Redis实例上加,从而确保即使某个节点发生故障,其他节点仍然能够继续工作并维持定状态的一致性和可用性。 #### 工作原理 为了提高可靠性和容错能力,算法建议至少使用五个相互独立的Redis服务器实例。客户端尝试在一个合理的时间窗口内连接到大多数(N/2+1, N为总的Redis实例数)以上的Redis实例,并成功设置。如果未能满足这一条件,则认为此次请求失败,所有已获得的都将被释放以便后续重试或其他进程获取资源访问权限[^2]。 具体来说: - **时间参数设定** - `TTL` (Time To Live): 的有效期限。 - `Retry Interval`: 当前轮询间隔时间内无法取得足够的票数时等待多久再次尝试。 - **执行流程** 当一个客户端想要获取时,会按照如下方式处理: 1. 记录当前时间戳作为起点; 2. 尝试依次向各个Redis实例发送命令去创建具有相同名称和随机值的新键(即代表此特定),并且指定其生存时间为`ttl`; 3. 统计有多少个成功的响应;只有超过半数以上才视为有效; 4. 如果整个过程耗时超过了预设的最大允许延迟(`retry interval * number of instances`)加上预期持有时间(ttl),则放弃这次竞争机会并将之前已经拿到手里的那些临时key删除掉以免造成死现象的发生; 一旦获得了合法的所有权之后就可以安全地开展受保护的操作了;而结束之后记得及时清除对应的标记以供他人正常使用. ```java // 使用Redisson库简化Java应用中的逻辑 import org.redisson.Redisson; import org.redISON.api.RLock; ... RLock lock = redisson.getLock("anyLock"); try { boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS); } finally { lock.unlock(); } ``` 上述代码片段展示了如何利用Redisson这个强大的工具包快速集成功能至应用程序之中[^3].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值