zookeeper与脑裂假死

zookeeper与脑裂假死

前言

高可用服务给我们应用带来可靠性的同时.也引出了一些问题.因为大多数高可用都是一个master多个slave.当master挂了.slave检测到就会提升为master.而这种检测机制就是心跳检测.但是心跳检测有时候会因为网络问题出现误判,触发了故障转移机制.从而导致原来master提供了服务.而新的master也在提供服务.从而造成脑裂的问题.而zookeeper作为协调服务,可以对他所管理的应用进行上锁然后竞争.失败的自动为slave.从而解决应用的脑裂问题.而今天我们主要说的是zookeeper自己集群的脑裂问题.虽然概率很低.但也是有发生的可能.

示例

hadoop鼻祖级应用,ResourceManager在整个hadoop中算是单点,为了实现其高可用,分为主备ResourceManager,zookeeper在其中管理整个ResourceManager。

可以想象,主备ResourceManager最初是主RM提供服务,如果一切安好,则zookeeper无用武之地。然而,总归会出现主RM提供不了服务的情况。于是会出现主备切换的情况,而zookeeper正是为主备切换保驾护航。

先来推理一下,主备切换会出现什么问题。传统的主备切换,可以让主备之间维持心跳连接,一旦备机发现主机心跳检测不到了,则自己切换为主机,原来的主机等待救援。这种方式有两个问题,一是由于网络抖动,负载过大等问题,备机检测不到心跳并不能说明主机一定挂了,有可能一定时间后主机或网络恢复,这时候主机并不知道备机已经切换为主机,2台主机互相争用,可能造成脑裂;二是如果一些数据集中在主机上面,则备机切换时由于同步延时势必会损失掉一部分的数据。

如何解决这些问题?早期的方式提供了不少解决方案,比如备机一旦切换为主机,则通过电源控制直接切断主机电源,简单粗暴,但是此刻备机已经是单点,如果主机是因为量撑不住而挂,那备机有可能会重蹈覆辙,最终导致整个服务不可用。

zookeeper又是如何解决这个问题的呢?

1. zookeeper作为第三方集群参与到主备节点中去,当主备启动时会在zookeeper上竞争创建一个临时锁节点,争用成功者则充当主机,其余备机

2. 所有备机会监听该临时锁节点,一旦主机与zookeeper间session失效,则临时节点被删除

3. 一旦临时节点被删除,备机开始重新申请创建临时锁节点,重新争用为主机;

4. 用zookeeper如何解决脑裂?实际上主机争用到节点后通过对根节点做一个ACL权限控制,则其他抢占的机器由于无法更新临时锁节点,只有放弃成为备机。

zookeeper使用了非常简单又现成的方式来解决的这个问题,比起其他方案方便不少,这也是为啥zookeeper流行的原因。说白了,就是把复杂操作封装化精简化

zookeeper简介

zookeeper是一个分布式应用程序的协调服务.他是一个为分布式应用提供一致性服务的软件.主要功能有 “配置管理,命名服务,分布式锁,集群管理”zookeeper是以Fast paxos 算为基础,因为paxos算法存在活锁问题.什么是活锁呢? 即当多个proposer(请求)交互提交时.有可能出现互相排斥而导致每个请求都不能提交成功.而Fast Paxos做了一些优化.通过先选举产生一个leader.只有leader才能提交proposer.

节点个数说明

单机的zookeeper可以用于开发测试环境.但是无法用于生产.生产环境需要配置成高可用集群模式,那么就涉及了节点个数的问题.

官方要求至少是数字为3的奇数节点.etcd和zookeeper有很多相似之处.同样也是至少三个节点.这是为了处理集群的选举问题.我会在下面详解.

三个节点可以允许我们坏1个,5个节点允许我们坏两个.多个节点可以提供更高的容错性.那是不是节点越多越好呢?不是这样的.因为节点越多,节点间通信越久.选举leader的时间越长.可能会因为过多的节点造成性能瓶颈和一系列问题.大多数情况3-5个节点足够了.

zookeeper节点的容错数

zookeeper集群中,在保证集群可用的情况下,最多能挂掉的节点个数称之为节点容错数.也叫集群容忍度

  • 5个节点中, 最多允许挂掉2个, 因为剩余的3个节点大于5/2;
  • 6个节点中, 最多允许挂掉2个, 因为剩余的4个节点大于6/2.

由此我们可以看到.5个节点和6个节点容错数相同.那么就没必要再选偶数个了.原因有以下几点

1.同样的容错数,节点多一个,选举速度就会慢一些.

2.如果是偶数个可能造成脑裂.例如集群有四个节点.同样发生脑裂.形成了AB两个小集群

A: 1个节点 B:三个节点 .或者A:三个节点 B:1个节点

A:2个节点 B:两个节点 

此时第一种可以选举 3>1  ,第二中 2=2无法选举集群对外无法提供服务

总结:

  • 节点数量为奇数个, 只要不出现过半的节点失效, 集群就总能对外提供服务;
  • 节点数量是偶数个, 如果有一半的节点失效, 就可能存在集群可用(脑裂成两个均等的子集群).

什么叫假死?

zookeeper如何判断一个节点死亡down掉了?在分布式系统中这些都是有监控者来判断的,但是监控者也很难判定其他的节点的状态,唯一一个可靠的途径就是心跳包括Zookeeper也是使用心跳来判断客户端是否仍然活着。
使用ZooKeeper来做master HA基本都是同样的方式,每个节点都尝试注册一个象征master的临时节点其他没有注册成功的则成为slaver,并且通过watch机制监控着master所创建的临时节点,Zookeeper通过内部心跳机制来确定master的状态,一旦master出现意外Zookeeper能很快获悉并且通知其他的slaver,其他slaver在之后作出相关反应。这样就完成了一个切换。这种模式也是比较通用的模式,基本大部分都是这样实现的,但是这里面有个很严重的问题,如果注意不到会导致短暂的时间内系统出现脑裂,因为心跳超时可能是master挂了,但是也可能是master 和其他节点之间网络出现了问题(比如网络负载大产生丢包)也同样可能导致而这种情况就是假死,此时选举但是与ZooKeeper之间的网络出现问题导致Zookeeper认为其挂掉了然后通知其他节点进行切换,这样slaver中就有一个成为了master,但是原本的master并未死掉,这时候client也获得master切换的消息,但是仍然会有一些延时zookeeper需要通讯需要一个一个通知,这时候整个系统就很混乱可能有一部分client已经通知到了连接到新的master上去了,有的client仍然连接在老的master上如果同时有两个client需要对master的同一个数据更新并且刚好这两个client此刻分别连接在新老的master上,就会出现很严重问题。

造成假死的根本原因?

主要原因是Zookeeper集群和Zookeeper client判断超时并不能做到完全同步,也就是说可能一前一后,如果是集群先于client发现那就会出现上面的情况。同时,在发现并切换后通知各个客户端也有先后快慢。一般出现这种情况的几率很小,需要master与Zookeeper集群网络断开但是与其他集群角色之间的网络没有问题,还要满足上面那些情况,但是一旦出现就会引起很严重的后果,数据不一致。

如何解决呢?

在slave切换的时候,不要检查到了master出现问题就立即切换,而是休眠一段时间,确保旧的master已经做好了shutdown和变更操作,然后slave再注册为新的master就能避免这个问题.这个休眠时间一般定义为zookeeper的超时时间.但是这段时间内zookeeper集群不可用.相对于脑裂数据不一致的问题,这点损失还是可以接受的.

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Loading...