linux 时钟漂移,Redis 实现分布式锁之Redlock 算法浅析

保证分布式锁有效的三个属性

Safety Properties:安全性,此处也就是互斥性,任意时刻只能有一个客户端可以持有锁

Liveness Property A:无死锁,即使持有锁的客户端崩溃或被分区,也可以获得锁

Liveness Property B:容错性,只要大多数 Redis 节点正常,客户端就能获取和释放锁

为什么基于故障转移(failover-based)的实现还不够

我们先来看看现有大多数 Redis 分布式锁的实现。

最简单的方案是在一个实例中创建一个 key,并给这个 key 设置过期时间,保证这个锁最终一定能够释放,当客户端释放锁的时候,删除这个 key

看上去可能不错,但是有个问题:当我们的 Redis 主节点挂掉时会发生什么?好,那我们增加一个从节点,当主节点不可用时自动切换到从节点。但不幸地是这不行,因为 Redis 复制是异步的,所以不能保证互斥性。

在这个方案下有一个明显的竞态条件:

客户端 A 在 master 节点获取锁;

在写 key 操作被传输到 slave 节点前 master 节点挂了;

slave 晋升为 master;

客户端 B 获取 A 其实刚刚已经获取到的锁;

SAFETY VIOLATION 违反了文章开头提到的安全属性

虽然有上述缺陷,但在一些特殊场景下,这种方案还是可以使用的。比如故障发生的时候,多个客户端同时持有锁对于系统运行或者业务逻辑没有太大影响,那么就可以使用这种基于复制的解决方案。否则最好还是使用本文后续将会提到的 Redlock 算法。

单实例情况下正确的实现

在解决单实例单点故障的限制前,我们先来看看如何正确地执行它

获取一个锁的方式:

set resource_name my_random_value NX PX 30000

解释:

在 resource_name 不存在(NX 选项)的时候创建它,并设置过期时间为 30000 毫秒。

值是一个随机值,而且这个值在每个客户端和每个锁请求中都是唯一的,这样做的目的是为了能够安全地释放锁,不会出现 A 客户端获取的锁被 B 客户端删除的情况。使用一段简单的 lua 代

你可能感兴趣的:(linux,时钟漂移)