Redis 的 Red Lock 是什么?你了解吗?

Sherwin.Wei Lv7

Redis 的 Red Lock 是什么?你了解吗?

回答重点

Red Lock,又称为红锁,是一种分布式锁的实现方案,旨在解决在分布式环境中使用 Redis 实现分布式锁时的安全性问题。

一般情况下,我们在生产环境会使用主从+哨兵方式来部署 Redis。

如果我们正在使用 redis 分布式锁,此时发生了主从切换,但从节点上不一定已经同步了主节点的锁信息

所以新的主节点上可能没有锁的信息。此时另一个业务去加锁,一看锁还没被占,于是抢到了锁开始执行业务逻辑。

此时就发生了两个竞争者同时进入临界区操作临界资源的情况,可能就会发生数据不一致的问题。

所以 Redis 官方推出了红锁,避免这种状况产生。它主要解决的问题就是当部分节点发生故障也不会影响锁的使用和数据问题的产生。

扩展知识

红锁实现原理

首先要使用红锁需要集群部署 redis,官方推荐至少 5 个实例,不需要部署从库和哨兵,仅需主库。

这 5 个实例(可以更多,我们按 5 个来讲述)之间没有任何关系(不同于 redis cluster),它们之间不需要任何信息交互。

客户端会对这 5 个实例依次申请锁,如果最终申请成功的数量超过半数(>=3),则表明红锁申请成功,反之失败。

再来看下异常情况。假设有一台实例宕机了怎么办?实际上没任何影响,因为理论上能申请成功的数量可以达到 4,超过了半数。

也因为没有主从机制,不会有同步丢失锁的问题。

具体加锁流程如下

1)客户端获取当前时间(t1)。

2)客户端按照顺序依次对 N 个 Redis 节点利用 set 命令进行加锁操作,对每个节点加锁都会设置超时时间(远小于锁的总过期时间),如果当前节点请求超时,立马向下一个节点申请锁。

3)当客户端成功从半数的 Redis 节点获取到了锁,这个时候获取一下当前时间 t2,然后计算加锁过程的总耗时 t(t2 - t1)。如果 t < 锁的过期时间,这个时候就可以判断加锁成功,反之加锁失败。

4)加锁成功则执行业务逻辑,加锁失败则依次向全部节点发起释放锁的流程。

上述的 set 加锁命令和解锁命令都遵循正常的分布式锁的使用规范,例如设置过期时间、唯一标识、lua 脚本释放等等。更详细可看面试鸭《redis 如何实现分布式锁 ?》这题。

红锁一定安全吗?

不一定。

来看下面这个图,是一位大佬 Martin Kleppmann 画的:

image.png

解释一下。如果 client 1 抢到了红锁,但是此时发生了 gc(垃圾回收),暂停(STW)了很久,与此同时 redis 中的锁过期了。

锁过期的同一时刻 gc 结束了,client 1 认为自己还持有锁,正常执行后续逻辑,而 client 2 也在此时拿到了锁,开始执行后续逻辑。

这不就有问题了吗?

除了 gc,如果出现时钟漂移,例如几个 redis 实例时间跳跃,导致锁提前过期了,也可能会造成别的 client 抢到锁。

所以,从理论上看红锁并不是无懈可击的,还是有概率出现问题,只不过这个概率非常小

业务上

从上面的内容大家也可以知道红锁的实现成本其实不低,需要有至少 5 个实例,而且因为要依次加锁,所以性能来说也比不上单实例的 redis 加锁,且极端环境下还是有问题。

所以一般业务上还是使用主从+哨兵来实现分布式锁。

Comments