|运维必备:Zookeeper集群“脑裂”问题处理大全( 二 )


那么Zookeeper选举的过程中为什么一定要有一个过半机制验证?
因为这样不需要等待所有zkServer都投了同一个zkServer就可以选举出来一个Leader了 。 这样比较快 , 所以叫快速领导者选举算法 。
Zookeeper过半机制中为什么是大于 , 而不是大于等于?
这就是跟脑裂问题有关系了 。 比如回到上文出现脑裂问题的场景 (如上图1):
当机房中间的网络断掉之后 , 机房1内的三台服务器会进行领导者选举 , 但是此时过半机制的条件是 ''节点数 > 3'' , 也就是说至少要4台zkServer才能选出来一个Leader 。
所以对于机房1来说它不能选出一个Leader , 同样机房2也不能选出一个Leader , 这种情况下整个集群当机房间的网络断掉后 , 整个集群将没有Leader 。
而如果过半机制的条件是 ''节点数 >= 3'' , 那么机房1和机房2都会选出一个Leader , 这样就出现了脑裂 。 这就可以解释为什么过半机制中是大于而不是大于等于 , 目的就是为了防止脑裂 。
如果假设我们现在只有5台机器 , 也部署在两个机房:
|运维必备:Zookeeper集群“脑裂”问题处理大全
本文插图

图3
此时过半机制的条件是 ''节点数 > 2'' , 也就是至少要3台服务器才能选出一个Leader 。
此时机房件的网络断开了 , 对于机房1来说是没有影响的 , Leader依然还是Leader;对于机房2来说是选不出来Leader的 , 此时整个集群中只有一个Leader 。
因此总结得出 , 有了过半机制 , 对于一个Zookeeper集群来说 , 要么没有Leader , 要么只有1个Leader , 这样Zookeeper也就能避免了脑裂问题 。
三、 Zookeeper集群''脑裂''问题处理
1、什么是脑裂?
简单点来说 , 脑裂(Split-Brain) 就是比如当你的 cluster 里面有两个节点 , 它们都知道在这个 cluster 里需要选举出一个 master 。 那么当它们两个之间的通信完全没有问题的时候 , 就会达成共识 , 选出其中一个作为 master 。
但是如果它们之间的通信出了问题 , 那么两个结点都会觉得现在没有 master , 所以每个都把自己选举成 master , 于是 cluster 里面就会有两个 master 。
对于Zookeeper来说有一个很重要的问题 , 就是到底是根据一个什么样的情况来判断一个节点死亡down掉了?在分布式系统中这些都是有监控者来判断的 , 但是监控者也很难判定其他的节点的状态 , 唯一一个可靠的途径就是心跳 , 所以Zookeeper也是使用心跳来判断客户端是否仍然活着 。
使用ZooKeeper来做Leader HA基本都是同样的方式:

  • 每个节点都尝试注册一个象征Leader的临时节点 , 其他没有注册成功的则成为follower , 并且通过watch机制 (这里有介绍) 监控着leader所创建的临时节点;
  • Zookeeper通过内部心跳机制来确定leader的状态 , 一旦Leader出现意外Zookeeper能很快获悉并且通知其他的follower , 其他flower在之后作出相关反应 , 这样就完成了一个切换 。 这种模式也是比较通用的模式 , 基本大部分都是这样实现的 。
但是这里面有个很严重的问题 , 如果注意不到会导致短暂的时间内系统出现脑裂 。 因为心跳出现超时可能是Leader挂了 , 但是也可能是Zookeeper节点之间网络出现了问题 , 导致Leader假死的情况 。
Leader其实并未死掉 , 但是与ZooKeeper之间的网络出现问题导致Zookeeper认为其挂掉了然后通知其他节点进行切换 , 这样follower中就有一个成为了Leader 。
但是原本的Leader并未死掉 , 这时候client也获得Leader切换的消息 , 仍然会有一些延时 , Zookeeper通讯需要一个一个通知 。
这时候整个系统在混乱中 , 很有可能有一部分client已经通知到了连接到新的Leader上去了 , 而有的client仍然连接在老的Leader上 。


推荐阅读