分布式锁的三种常用实现

网上这个博客一大堆呀,有好有坏。这里简单总结一下。
https://www.hollischuang.com/archives/1716
这个文章我觉得还可以。

常见的是三种方法:基于数据库,基于缓存(redis),基于zookeeper。

难点:设计可重入的锁逻辑都复杂一些。+1的时候容易,但是在删除的时候比较麻烦,得保证你删除的时候没有人再去写。

优缺点

比较 可靠性 性能 缺点 优点
数据库 单点故障/如果主从,主从异步存在一致性问题,主从同步则存在性能问题 差(百级别) 没有超时机制,再超时时候得注意抢锁的逻辑。如果是用insert的方式,没有client的通知,只能循环等。如果采用行锁,则可能存在连接池的问题,同时sql本身连接超时的问题 数据持久化,另外至少是能支持下跨机房,redis也许将就,zk总不能做跨机房方案吧?
缓存redis 单点故障/如果是主从或者cluster,同步都是异步的,数据一致性问题 高(十万级别) 没有通知机制,就是轮询 有超时机制,但是这个超时的时间要自己设置
zookeeper 网络抖动导致断开连接,会导致其他的以为自己拿到了锁 中等(万/千级别) 就是网络抖动就直接没锁啦 一旦进程挂掉,自动释放锁,其他等待会获得提醒

我个人倾向于再高并发场景下用redis,出现故障的时候也需要容忍这样的问题。
但是如果是特别关键的数据,那我觉得可能数据库更保险一些,牺牲性能和A,来保证强C。不过我觉得场景不是太多。
至于这个ZK,我理解不是太主流的。

另外对于db的超时清理,也不要直接去delete。
例子:A insert了那行然后挂了,B,C同时发现了已经超时了,如果都是delete+insert again的话,那B执行快了一点儿,delete掉有insert了。C和B同时发现的,则直接也去delete,但是现在delete是B刚insert进去的,然后再insert一下,这个时候B也认为自己拿着锁,C也认为自己拿着锁。所以这个时候起码要做带check的删除。


下面就有意思了,讨论了redis的分布式锁redlock算法。以及一些争论,非常好看,也非常有启发。
基于Redis的分布式锁到底安全吗(上)
基于Redis的分布式锁到底安全吗(下)
How to do distributed locking

我觉得有几个注意点,还是要自己思考下:
在上篇中提到:

“为了应对这一问题,antirez又提出了延迟重启(delayed restarts)的概念。也就是说,一个节点崩溃后,先不立即重启它,而是等待一段时间再重启,这段时间应该大于锁的有效时间(lock validity time)。这样的话,这个节点在重启前所参与的锁都会过期,它在重启后就不会对现有的锁造成影响。”

开始我理解是有个节点down了,就设置这个cluster的size-1,如果这样的话,down两个节点就会有错误了。所以即使有节点down掉,仍然维持原有的size,这样即使down掉1+个也不会出现错误。

下篇中:

“Check and Set”对于写操作要分成两步来完成(设置token、判断-写回),而递增的fencing token机制只需要一步(带着token向资源服务器发起写请求)。

我理解哈,对于fencing token,也依然应该是两部。对于分布式的客户端,必须在第一步拿到全局(或者对资源的)递增数字,这个就需要一个全局的管理,或者目标资源的管理。总是需要额外的一步吧。

下篇中:

在本文的讨论中,我们在分布式锁的正确性上走得最远的地方,要数对于ZooKeeper分布式锁、单调递增的epoch number以及对分布式资源进行标记的分析了。请仔细审查相关的论证。

其实这里我不是太过于同意,我理解的哈,在实际中,ZK的心跳丢失(网络或者GC)比机器的时间跳跃要更容易发生。所以我觉得ZK的实际应用并不能比redlock要好。对于另外两个,我觉得还是赞同的。

你可能感兴趣的:(分布式锁的三种常用实现)