ZooKeeper 故障恢复

来源:互联网 发布:钢铁力量6级天炉数据 编辑:程序博客网 时间:2024/05/29 17:50

在介绍ZooKeeper处理节点故障的机制之前,我想先给大家讲一讲在一切都正常的情况下,ZooKeeper是如何工作的,也就是ZooKeeper处理客户端请求的流程。当然我只侧重讲解客服端的写请求部分。

过程如下:
这里写图片描述
在这主要的6步过程中,任何与之相关的节点都有可能出现故障,那么zooKeeper是如何来处理的呢,以保证服务的高可用性和一致性?

若ZooKeeper客户端节点发生故障时,他正处于空闲状态,则按照session失效处理。而复杂的情况是ZooKeeper客户端节点发生故障是,他正在等待ZooKeeper服务器端的请求响应。下面将对ZooKeeper客户端节点发生故障的时机进行详细的分类讨论。

但是在此之前,我还想简单的介绍一下ZooKeeper中session的概念。我们知道ZooKeeper允许客户端创建两种类型的节点:persistent、ephemeral,ephemeral类型的节点是与创建它的客户端一起共存亡的。那么这中间就有问题,ZooKeeper是如何知道客户端还存不存在呢?ZooKeeper是使用session来解决这个问题的,这也是为什么我们在客户端创建ZooKeeper实例时需要传入一个sessionout的参数。当客户端与Follower连接时,实际上是成功创建了一个session,Follower和Leader都保存了这个session信息(实际上Session的建立也是需要Leader同意的)。一方面,客户端会定期的向Follower发送Ping包来告诉这个Follower我还活着;另一方面,Leader也会定期向Follower发送ping包,一则检测它的Follower们是否至少有超过一半还活着,二则Follower们返回他们各自正在服务的客户端(未超时的session),来告诉Leader那些客户端还活着,这样Leader就可以删除那些客户端已经不存在的ephemeral类型的节点。ok,关于这个session问题我们先暂时讨论到这里,下面我们来看看当正在工作的客户端节点发生故障的,ZooKeeper系统是如何来处理的吧。

1.Follower在第2步时若没有发现客户端已经发生了故障,则他会进行第2步,否则,他将会丢弃该客户端的请求包。

2.Leader在第3步时还没有发现客户端已经发生了故障,那么后面的第4、5步都会顺利执行。对于第6步,若此时Follower已经发现了该客户端已发生故障,则它不会向客户端发送响应包,而直接从FinalRequestProcessor处理器中返回;若此时Follower还没有发现该客户端已发生故障,则FinalRequestProcessor会将响应包交给对应的NIOServerCnxn,而NIOServerCnxn在发送该响应包时,会抛出异常,但并没有对该异常做任何处理。

3.Leader在第3步时发现了客户端已经发生了故障,那么后面的第4、5步都会顺利执行,只不过此时的操作类型就是OpCode.error,然后直接从FinalRequestProcessor处理器中返回,而不会发生第6步了。

4.从上面的分析我们可以看出,第4、5步并不会收到客户端是否发生故障的影响。

我们知道,当某一个Follower或Observer发生故障时,与之直接相连的ZooKeeper客户端就不可能再从Follower或Observer收到正在处理的请求的响应包,因此,它会丢弃正在处理的请求,并通知客户。而ZooKeeper客户端则会重新选择一个Follower或Observer,并与之建立联系为客户端服务,请注意,这个过程对用户是透明的。

1.Follower在处理第2步之前发生故障,则处理情况如上所诉,只涉及到ZooKeeper客户端;若Follower在处理第2步之后发生故障,则,Leader最迟会在执行第3步的时候发现Follower发生了故障,尽管Leader发送的提案和提交,Follower收不到,Leader也不会收到Follower的投票,但这并不会影响Leader的处理,只要当前还有超过半数的follower存活着。

2.从上可以看出,单个Follower节点的实效对整个ZooKeeper服务集群根本就不会产生“任何”的影响,所以单个Follower在任何时刻的失效,系统仍然会比较稳定的继续运行。

在这里,可能有些人会问,如果某一个Follower实效,则Leader就不能得到该Follower管理的session的信息,之后Leader可能会误认为与该Follower相连的若干ZooKeeper客户端实效。没错,是这样的,但这种情况的处理同ZooKeeper客户端发生故障是一样的。

最后,我就想讨论一下Leader节点发生故障的情况下,ZooKeeper的处理机制。

1.若Leader节点在第2步之前发生了故障,则Follower的第2步不会执行成功,但该请求包被添加到了Follower的pendingSyncs集合中,同时Follower再次之前就已经发现Leader已经实失效,退出Follower角色,同时关闭与之相连的客户端,并不在。之后,Follower就会参入Leader的选举中,而在选举的过程中,该节点不会再接受任何客户端的连接。

2.若Leader节点在第2步之后,第3步之前发生了故障,处理同1。

3.若Leader节点在第3步之后,第4步之前发生了故障,处理同1。

4.若Leader节点在第4步之后,第5步之前发生了故障,处理同1。

5.若Leader节点在第5步之后,第6步之前发生了故障,则Folloer的处理同1的同时,也会执行第6步操作。

0 0