内容简介:Martin上来就问,咱们要锁来干啥呢?2个缘由:对于第1种缘由,咱们对锁是有必定宽容度的,就算发生了两个节点同时工做,对系统的影响也仅仅是多付出了一些计算的成本,没什么额外的影响。这个时候 使用对于第2种缘由,对正确性严格要求的场景(好比订单,或者消费),就算使用了 RedLock 算法仍然html
Martin上来就问,咱们要锁来干啥呢?2个缘由:redis
对于第1种缘由,咱们对锁是有必定宽容度的,就算发生了两个节点同时工做,对系统的影响也仅仅是多付出了一些计算的成本,没什么额外的影响。这个时候 使用 单点的 Redis 就能很好的解决问题,没有必要使用RedLock,维护那么多的 Redis 实例,提高系统的维护成本。算法
对于第2种缘由,对正确性严格要求的场景(好比订单,或者消费),就算使用了 RedLock 算法仍然 不能保证锁的正确性 。编程
咱们分析一下 RedLock 的有啥缺陷吧:安全
做者 Martin 给出这张图,首先咱们上一讲说过,RedLock中,为了防止死锁,锁是具备过时时间的。这个过时时间被 Martin 抓住了小辫子。服务器
这还了得,数据就发生了错误。RedLock 只是保证了锁的高可用性,并无保证锁的正确性。网络
这个时候也许你会说,若是 Client 1 在提交任务以前去查询一下锁的持有者是不本身就能解决这个问题?架构
答案是否认的,FGC 会发生在任什么时候候,若是 FGC 发生在查询以后,同样会有如上讨论的问题。运维
那换一个没有 GC 的编程语言?异步
答案仍是否认的, FGC 只是形成系统停顿的缘由之一,IO或者网络的堵塞或波动均可能形成系统停顿。
Martin给出了一个解决的方案:
为锁增长一个 token-fencing。
咱们其实能够理解这个 token-fencing 就是一个乐观锁,或者一个 CAS。
Martin 还指出了,RedLock 是一个 严重依赖系统时钟 的分布式系统。
仍是这个过时时间的小辫子。若是某个 Redis Master的系统时间发生了错误,形成了它持有的锁提早过时被释放。
这个时候 Martin 又提出了一个至关重要的关于分布式系统的设计要点:
好的分布式系统应当是异步的,且不能时间做为安全保障的。由于在分布式系统中有会程序暂停,网络延迟,系统时间错误,这些因数都不能影响分布式系统的安全性,只能影响系统的活性(liveness property)。换句话说,就是在极端状况下, 分布式系统顶多在有限的时间内不能给出结果,可是不能给出错误的结果 。
因此总结一下 Martin 对 RedLock 的批评:
这个时候感受醍醐灌顶,简直写的太好了。
RedLock 的做者,同时也Redis 的做者对 Martin的文章也作了回应,条理也是至关的清楚。
antirez 看到了 Martin 的文章之后,就写了一篇文章回应。剧情会不会反转呢?
antirez 总结了 Martin 对 RedLock的指控:
对于第一个问题:
antirez 洋洋洒洒的写了不少,仔细看半天,也没有解决我心中的疑问。回顾一下RedLock 获取锁的步骤:
若是,程序在1-3步之间发生了阻塞,RedLock能够感知到锁已通过期,没有问题。
若是,程序在第 4 步以后发生了阻塞?怎么办???
答案是,其余 具备自动释放锁的分布式锁都没办解决这个问题 。
对于第二个质疑:
antirez 认为,首先在实际的系统中,从两个方面来看:
对于第1个问题。上文已经提到了,RedLock作了一些微小的工做,可是没办法彻底避免。其余带有自动释放的分布式锁也没有办法。
第2个问题,Martin认为系统时间的阶跃主要来自两个方面:
对于人为修改,能说啥呢?人要搞破坏没办法避免。
NTP受到一个阶跃时钟更新,对于这个问题,须要经过运维来保证。须要将阶跃的时间更新到 服务器 的时候,应当采起小步快跑的方式。屡次修改,每次更新时间尽可能小。
因此严格来讲确实, RedLock创建在了 Time 是可信的模型上,理论上 Time 也是发生错误,可是在现实中,良好的运维和工程一些机制是能够最大限度的保证 Time 可信。
最后, antirez 还打出了一个暴击,既然 Martin 提出的系统使用 fecting token 保证数据的顺序处理。还须要 RedLock,或者别的分布式锁干啥??
每个系统设计都有本身的侧重或者局限。工程也不是完美的。在现实中工程中不存在完美的解决方案。咱们应当深刻了解其中的原理,了解解决方案的优缺点。明白选用方案的局限性。是否能够接受方案的局限带来的后果。
架构原本就是一门平衡的艺术。
简单来讲,单实例Redis能解决大部分的分布式锁需求。Redlock的引入意义不大,若是对可用性要求更高的话,使用其余方案也许是更好的选择。