能够先看下以前写的实现分布式锁的方案redis
分布式锁的实现数据库
而后再来看下下面的总结。服务器
redis、数据库等实现的分布式锁,须要设置锁超时时间的缘由在于:其余客户端没法得知已经获取锁的客户端的状态 是挂了呢,仍是正在执行。因此只能傻傻的设置一个超时,认为超时以后就简单的断定获取锁的客户端挂了。微信
一旦锁设定了超时时间,可能获取锁的客户端因各类缘由执行业务操做的时候耗时较长,超出了锁的超时时间,这时其余客户端就能够再次获取锁了,因此就会带来并发问题。网络
为了消除这个锁超时,就须要由服务器来做为代理来通知,session
如ZooKeeper,一旦客户端挂了,就会删除对应的临时节点,而后通知watch该节点的其余客户端。因此客户端不须要设置锁超时,就等待通知便可。架构
从这点来讲ZooKeeper是更可靠的,下降了因锁超时带来的并发问题。并发
redis、数据库等方案要想实现高可用,则必须有对应的高可用方案。如最简单的主从架构,又引入了一致性的问题,又会有不少的坑。分布式
ZooKeeper方案自己能够作到高可用、一致性,因此ZooKeeper方案也更简单一些。布局
这个单点不是说redis或zookeeper的单点问题,而是客户端和服务器端的这个链接的单点问题。先来举个例子:
如ZooKeeper仍是会出现并发问题的,如客户端获取到锁了以后,和ZooKeeper链接出现了session超时, 就会致使ZooKeeper集群删除对应的临时节点,其余客户端也就能获取到锁了,此时就存在并发问题。
这种问题的根由就是:客户端和ZooKeeper集群之间的链接是单链接,即只链接其中的一台机器。一旦该链接出现网络抖动, 这种分布式锁方案也会出现并发问题。
减小并发的措施:增大session的超时时间,尽可能减小网络抖动,可是这也会下降服务器端对客户端的状态检测的灵敏度,这个灵敏度在分布式锁的场景下也不是特别重要,因此无所谓了。
要消除单点,必然是创建多链接来防止网络的抖动,即客户端链接多个服务器端,向每一个服务器都执行获取锁的操做。
如redis的Redlock实现的分布式锁。
有N个独立的master服务器,客户端会向全部的服务器发送获取锁的操做。过半的服务器都获取到锁了则认为获取到锁了,这种也有不少细节。这种方式就解决了上述所说的ZooKeeper单链接可能形成的并发问题。
然而redis因为上述1所说的redis自身设计的问题,Redlock实现的分布式锁也会有锁超时问题,即也会存在并发。
因此理想中更好的方案就是:解决了上述2个问题,从而来进一步减小并发的可能性。
redis若是能像ZooKeeper同样,实现了和客户端绑定的临时key,一旦redis客户端挂了,临时key删除,通知watch该key的其余客户端(感受这个是一个不错的需求,不知redis将来是否要实现),就能够消除锁超时,再使用Redlock实现的分布式锁,这时候可靠性就更高了。
本文侧重总结在可靠性方面的问题,性能嘛,单机的redis固然是最快的了,其次zookeeper,最后数据库。而上述第五点,Redlock方案牺牲了一些性能来换取了可靠性。
其实要解决2个高可用的问题:
数据存储的高可用(解决基本使用)
如使用redis、数据库、ZooKeeper,他们承载着分布式锁须要的数据,不能是单点的,要集群高可用
链接的高可用(下降并发的几率)
那就须要创建多链接,如向N个redis master创建链接,向每个都获取锁。
因此应该理想的布局是:
和N个独立的服务器(如ZooKeeper)都创建链接,向每台服务器都请求获取锁的操做,过半成功才表示获取到锁
这N个独立的服务器既有数据的保障,又有多链接的保障。因此简单来讲,应该和3个独立的ZooKeeper机器都创建链接,而不是这3台构成一个ZooKeeper集群。
欢迎继续来讨论,越辩越清晰。
欢迎关注微信公众号:乒乓狂魔