回答
RedLock
并不一定是绝对安全的,主要存在如下两个问题:
- 脑裂:在分布式系统中,网络脑裂是指系统的不同部分因为网络故障而无法相互通信。在使用 RedLock 算法时,如果发生了网络脑裂,可能会导致集群被分割成两个或多个互不通信的子集,那么在每个网路分区内,客户端可能都能从该分区内可达的大多数 Redis 实例中获取到锁。因为每个分区内的 Redis 实例是无法感知到其他分区的状态,它们会独立做出“锁可用”的决定,从而导致多个客户端会获取同一把分布式锁。
- 时钟漂移:在
RedLock
中,所有节点的过期时间是一样的,如果发生了时钟漂移,导致某些节点的锁过期时间比其他节点早,这些节点的锁资源提前释放了。那么就会存在RedLock
还没有完全被释放掉就被另一个客户端获取的情况。这种情况下,即使客户端在大多数节点上成功获取了锁,也无法保证锁的安全性,因为锁可能因为某些节点的时钟漂移而被错误地认为已经释放了。
扩展
Redis 作者 Antirez
提出 RedLock
方案后,立刻就遭到英国剑桥大学、业界著名的分布式系统专家 Martin
的质疑!它认为 Antirez
提出的 RedLock
算法模型有问题,写了一篇文章列出 RedLock
的算法问题,并提出了自己的看法。
而 Antirez
也不甘示弱,也写了一篇文章来反驳。
两位大神的原文:
- Martin:https://news.ycombinator.com/item?id=11059738
- Antirez:https://news.ycombinator.com/item?id=11065933
下面的内容是对这两篇文章的解读。
Martin 对于 Relock 的质疑
在 Martin
大神的文章中主要是阐述了 4 点:
- 使用分布式锁的目的
- 锁在分布式系统中遇到的问题
- 时钟不正确导致的问题
- fecing token 方案
使用分布式锁的目的
Martin
表示我们使用 Redis 来实现分布式锁的主要目的是两点。
- 效率:使用分布式锁的互斥能力,避免多次做重复的工作。这种情况即使锁失效,也不会带来「恶性」的后果。例如多发了 1 次邮件、多计算一次都是无伤大雅的场景。但是
Martin
认为,如果是为了效率,单机版的 Redis 效率更高,即使发生偶尔的宕机也不会产生很严重的问题。使用RedLock
太重了,没有必要。 - 正确性:使用锁是为了防止多个线程互相竞争,保证线程安全,如果锁失效,则会发生线程不安全,导致数据不一致,影响比较恶劣。然而,
Martin
认为RedLock
根本无法达到安全的效果,会存在锁失效的情况。
所以,无论是效率还是正确性,Martin
认为 RedLock
都达不到。