ZooKeeper 05 - ZooKeeper 集群的脑裂问题(Split Brain)
首发于 2018-12-08,修改于 2021-12-12。
1 - ZooKeeper的主从机制
在绝大部分通过主从实现高可用的系统中,Leader == Master,Follower == Slaver。
集群中的各个节点都会尝试注册为 leader 节点,其他没有注册成功的则成为 follower(随从)节点。
这些 follower 节点通过 watcher(观察者)监控着 leader 节点:
—— ZooKeeper 内部通过心跳机制来确定 leader 的状态,一旦 leader 节点出现问题,集群内部就能立即获悉并迅速通知其他 follower 节点来选出新的 leader。
2 - 什么是 ZooKeeper 的脑裂
2.1 脑裂现象的表现
ZooKeeper 集群中,各个节点间的网络通信不良时,容易出现脑裂(split-brain)现象。
1)集群中的部分 follower 节点监听不到 leader 节点的心跳,就会认为 leader 节点出了问题;
2)这些监听不到 leader 节点心跳的 follower 节点就会选举出新 leader 节点;
3)新的 leader 和旧 leader 节点 和各自的 follower 节点组成多个小集群。
—— 一个集群中有多个 leader 节点,这就是脑裂现象。
2.2 为什么会出现脑裂
设想这样一种情况:
① 集群中网络通信不好,导致心跳监测超时 —— follower 认为 leader 节点由于某种原因挂掉了,可其实 leader 节点并未真正挂掉 —— 这就是假死现象。
② leader 节点假死后,ZooKeeper 通知所有 follower 节点进行新的选举 ==> 某个 follower 节点升级为新的 leader —— 此时集群中存在2个leader节点。
③ 此时 ZooKeeper 需要将新 leader 节点的信息通知给所有 follower 节点,还要通知到所有的 client(比如 Kafka 集群中的 Kafka 节点就是一个 client),这个过程由于网络等因素的影响,消息到达肯定存在不同程度的延迟。
④ 如果部分 client 获得了新 leader 节点的信息,而部分没有获得,恰好此时 client 向 ZooKeeper 发起读写请求,ZooKeeper 内部的不一致就会导致:部分 client 连接到了新的 leader 节点,而部分 client 连接到了旧的 leader节点 —— 服务中出现了2个leader,client 不知道听谁好,就像1个大脑被分裂成2个,很形象吧O(∩_∩)O
3 - ZooKeeper如何解决"脑裂"
3.1 3种可行的思路
(1) Quorums(ˈkwɔrəm,法定人数)
通过设置法定人数,进而确定集群的容忍度,当集群中存活的节点少于法定人数,集群将不可用。比如:
3个节点的集群中,Quorums = 2 —— 集群可以容忍 (3 - 2 = 1) 个节点失败,这时候还能选举出 leader,集群仍然可用;
4个节点的集群中,Quorums = 3 —— 集群同样可以容忍 1 个节点失败,如果2个节点失败,那整个集群就不可用了。
(2) Redundant communications(冗余通信)
集群中采用多种通信方式,防止一种通信方式失效导致集群中的节点无法通信。
(3) Fencing(隔离,即共享资源)
通过隔离的方式,将所有共享资源隔离起来,能对共享资源进行写操作(即加锁)的节点就是 leader 节点。
3.2 ZooKeeper 的做法
ZooKeeper 默认采用了Quorums 的方式:只有获得超过半数节点的投票,才能选举出 leader。
这种方式可以确保要么选出唯一的 leader,要么选举失败。
ZooKeeper 中 Quorums 的作用:
① 指定集群中选举 leader 所需的最少节点数,保证集群可用;
② client 的数据被安全保存到集群中所需的最少节点数,一旦这些节点保存了数据,客户端将被通知数据已经安全保存,可以继续其他任务 —— 基于最终一致性,集群中剩余的节点最终也会保存相关的数据。
ZooKeeper的写也遵循quorum机制,因此得不到大多数支持的写是无效的。
3.3 ZooKeeper 的具体解决思路
假设:leader 发生了假死,followers 选举出了一个新的 leader。
当旧的 leader 复活并认为自己仍然是 leader,它向其他 followers 发出写请求时,会被拒绝。
—— 因为 ZooKeeper 维护了一个叫 epoch 的变量,每当新 leader 产生时,epoch 就会递增,followers 如果确认了新的 leader,同时也会知道其 epoch 的值 —— 它们会拒绝所有 epoch 小于现任 leader 的 epoch 的旧 leader 的请求。
注意:仍然会存在有部分 followers 不知道新 leader 的存在,但肯定不是大多数,否则新 leader 将无法产生。
参考资料
版权声明
出处:博客园-瘦风的南墙(https://www.cnblogs.com/shoufeng)
感谢阅读,公众号 「瘦风的南墙」 ,手机端阅读更佳,还有其他福利和心得输出,欢迎扫码关注🤝
本文版权归博主所有,欢迎转载,但 [必须在页面明显位置标明原文链接],否则博主保留追究相关人士法律责任的权利。