红锁算法理解

举报
yd_249383650 发表于 2023/05/23 09:59:33 2023/05/23
【摘要】 redis集群状态下的问题:1. 客户端A从master获取到锁2. 在master将锁同步到slave之前,master宕掉了。3. slave节点被晋级为master节点4. 客户端B取得了同一个资源被客户端A已经获取到的另外一个锁。安全失效! 解决集群下锁失效,参照redis官方网站针对redlock文档:https://redis.io/topics/distlock在算法的分布式版...

redis集群状态下的问题:

1. 客户端A从master获取到锁

2. 在master将锁同步到slave之前,master宕掉了。

3. slave节点被晋级为master节点

4. 客户端B取得了同一个资源被客户端A已经获取到的另外一个锁。

安全失效! 解决集群下锁失效,参照redis官方网站针对redlock文档:https://redis.io/topics/distlock

在算法的分布式版本中,我们假设有N个Redis服务器。这些节点是完全独立的,因此我们不使用复制或 任何其他隐式协调系统。前几节已经描述了如何在单个实例中安全地获取和释放锁,在分布式锁算法 中,将使用相同的方法在单个实例中获取和释放锁。将N设置为5是一个合理的值,因此需要在不同的 计算机或虚拟机上运行5个Redis主服务器,确保它们以独立的方式发生故障。为了获取锁,客户端执行以下操作:

1. 客户端以毫秒为单位获取当前时间的时间戳,作为起始时间。

2. 客户端尝试在所有N个实例中顺序使用相同的键名、相同的随机值来获取锁定。每个实例尝试获取 锁都需要时间,客户端应该设置一个远小于总锁定时间的超时时间。例如,如果自动释放时间为10秒,则尝试获取锁的超时时间可能在5到50毫秒之间。这样可以防止客户端长时间与处于故障状 态的Redis节点进行通信:如果某个实例不可用,尽快尝试与下一个实例进行通信。

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

4. 如果获取了锁,则将锁有效时间减去 获取锁所花费的时间,如步骤3中所计算。

5. 如果客户端由于某种原因(无法锁定N / 2 + 1个实例或有效时间为负)而未能获得该锁,它将尝试 解锁所有实例(即使没有锁定成功的实例)。 每台计算机都有一个本地时钟,我们通常可以依靠不同的计算机来产生很小的时钟漂移。只有在拥有锁 的客户端将在锁有效时间内(如步骤3中获得的)减去一段时间(仅几毫秒)的情况下终止工作,才能 保证这一点。以补偿进程之间的时钟漂移


当客户端无法获取锁时,它应该在随机延迟后重试,以避免同时获取同一资源的多个客户端之间不同步 (这可能会导致脑裂的情况:没人胜)。同样,客户端在大多数Redis实例中尝试获取锁的速度越快, 出现裂脑情况(以及需要重试)的窗口就越小,因此理想情况下,客户端应尝试将SET命令发送到N个 实例同时使用多路复用。 值得强调的是,对于未能获得大多数锁的客户端,尽快释放(部分)获得的锁有多么重要,这样就不必 等待锁定期满才能再次获得锁(但是,如果发生了网络分区,并且客户端不再能够与Redis实例进行通 信,则在等待密钥到期时需要付出可用性损失)。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。