作者:cang桑哥哥 | 来源:互联网 | 2023-10-11 12:52
接上篇《ZooKeeper 技术知识总结之一——Leader选举算法》
二. ZK 惊群与脑裂
2.1 Zookeeper 的惊群现象
ZooKeeper 的节点通常可以作为分布式锁来使用。比如可以多个服务对同时竞争申请一个节点 “/test/lock”,创建成功的服务获取到这个锁,其他没创建成功的监听这个锁,等到这个锁释放后再重新申请该锁。这样就实现了简单的分布式锁。
但同时在大量锁的情况下会有**“惊群”**的问题。“惊群”就是在一个节点删除的时候,大量对这个节点的删除动作有订阅Watcher的线程会进行回调,这对Zk集群是十分不利的。所以需要避免这种现象的发生。
为了解决“惊群“问题,我们需要放弃订阅一个节点的策略,那么怎么做呢?
- 我们将锁抽象成目录,多个线程在此目录下创建瞬时的顺序节点,因为Zk会为我们保证节点的顺序性,所以可以利用节点的顺序进行锁的判断。
- 首先创建顺序节点,然后获取当前目录下最小的节点,判断最小节点是不是当前节点,如果是那么获取锁成功,如果不是那么获取锁失败。
- 获取锁失败的节点获取当前节点上一个顺序节点,对此节点注册监听,当节点删除的时候通知当前节点。
- 当unlock的时候删除节点之后会通知下一个节点。
2.2 脑裂现象与 Zookeeper
参考地址:《脑裂是什么?Zookeeper是如何解决的?》
脑裂 (split-brain),就是“大脑分裂”,也就是本来一个“大脑”被拆分了两个或多个“大脑”。我们都知道,如果一个人有多个大脑,并且相互独立的话,那么会导致人体“手舞足蹈”,“不听使唤”。这种现象经常出现于集群情况。
对于一个集群,想要提高这个集群的可用性,通常会采用多机房部署,比如现在有一个由6台 zkServer 所组成的一个集群,部署在了两个机房。正常情况下,此集群只会有一个 Leader。那么如果机房之间的网络断了之后,两个机房内的 zkServer 还是可以相互通信的,如果不考虑过半机制,那么就会出现每个机房内部都将选出一个 Leader,如下图所示:
实际上 Zookeeper 集群中是不会出现脑裂问题的,而不会出现的原因就跟过半机制有关。Zookeeper 选举时,必须接收到超过一半节点选择同样的节点,超过一半节点意味着不能等于一半节点。这里的原因用上面的问题可以很好的解释:
假设允许等于一半节点,那么假设两个机房都是三台服务器,中间两个机房的连接断了,那么两个机房内部选举,都会选出分别的 master,即出现了脑裂现象。
但是如果只允许大于一半节点,不允许等于,那么上面的情况,两边机房都不会选出新的 master。如果两个机房分别是 4 台,2 台节点,那么机房一所有节点的投票最终会相同,投票数量为 4,大于总服务器的一半,所以新的 master 节点只可能出现在机房一中。