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


如果同时有两个client需要对Leader的同一个数据更新 , 并且刚好这两个client此刻分别连接在新老的Leader上 , 就会出现很严重问题 。
这里做下小总结:

  • 假死:由于心跳超时(网络原因导致的)认为Leader死了 , 但其实leader还存活着;
  • 脑裂:由于假死会发起新的Leader选举 , 选举出一个新的Leader , 但旧的Leader网络又通了 , 导致出现了两个Leader, 有的客户端连接到老的Leader , 而有的客户端则连接到新的leader 。
2、Zookeeper脑裂是什么原因导致的?
主要原因是Zookeeper集群和Zookeeper client判断超时并不能做到完全同步 , 也就是说可能一前一后 , 如果是集群先于client发现 , 那就会出现上面的情况 。
同时 , 在发现并切换后通知各个客户端也有先后快慢 。 一般出现这种情况的几率很小 , 需要Leader节点与Zookeeper集群网络断开 , 但是与其他集群角色之间的网络没有问题 , 还要满足上面那些情况 , 但是一旦出现就会引起很严重的后果 , 数据不一致 。
3、Zookeeper是如何解决''脑裂''问题的?
要解决Split-Brain脑裂的问题 , 一般有下面几种种方法:
  • Quorums (法定人数) 方式:比如3个节点的集群 , Quorums = 2, 也就是说集群可以容忍1个节点失效 , 这时候还能选举出1个lead , 集群还可用 。 比如4个节点的集群 , 它的Quorums = 3 , Quorums要超过3 , 相当于集群的容忍度还是1 , 如果2个节点失效 , 那么整个集群还是无效的 。 这是Zookeeper防止''脑裂''默认采用的方法;
  • Redundant communications (冗余通信)方式:集群中采用多种通信方式 , 防止一种通信方式失效导致集群中的节点无法通信 。
  • Fencing (共享资源) 方式:比如能看到共享资源就表示在集群中 , 能够获得共享资源的锁的就是Leader , 看不到共享资源的 , 就不在集群中 。
  • 仲裁机制方式;
  • 启动磁盘锁定方式 。
要想避免Zookeeper''脑裂''情况其实也很简单 , 在follower节点切换的时候不在检查到老的Leader节点出现问题后马上切换 , 而是在休眠一段足够的时间 , 确保老的leader已经获知变更并且做了相关的shutdown清理工作了 , 然后再注册成为master就能避免这类问题了 。
这个休眠时间一般定义为与Zookeeper定义的超时时间就够了 , 但是这段时间内系统可能是不可用的 , 但是相对于数据不一致的后果来说还是值得的 。
1)ZooKeeper默认采用了Quorums这种方式来防止''脑裂''现象
即只有集群中超过半数节点投票才能选举出Leader 。
这样的方式可以确保Leader的唯一性,要么选出唯一的一个Leader , 要么选举失败 。 在zookeeper中Quorums作用如下:
  • 集群中最少的节点数用来选举Leader保证集群可用;
  • 通知客户端数据已经安全保存前集群中最少数量的节点数已经保存了该数据 。 一旦这些节点保存了该数据 , 客户端将被通知已经安全保存了 , 可以继续其他任务 。 而集群中剩余的节点将会最终也保存了该数据 。
假设某个Leader假死 , 其余的followers选举出了一个新的Leader 。 这时 , 旧的Leader复活并且仍然认为自己是Leader , 这个时候它向其他followers发出写请求也是会被拒绝的 。
因为每当新Leader产生时 , 会生成一个epoch标号(标识当前属于那个Leader的统治时期) , 这个epoch是递增的 , followers如果确认了新的Leader存在 , 知道其epoch , 就会拒绝epoch小于现任Leader epoch的所有请求 。
那有没有follower不知道新的Leader存在呢?有可能 , 但肯定不是大多数 , 否则新Leader无法产生 。 Zookeeper的写也遵循quorum机制 , 因此 , 得不到大多数支持的写是无效的 , 旧Leader即使各种认为自己是leader , 依然没有什么作用 。


推荐阅读