其他分享
首页 > 其他分享> > Zookeeper一致性协议Zab详解

Zookeeper一致性协议Zab详解

作者:互联网

zookeeper是分布式协调系统,用来协调、同步多服务器之间的状态,容错能力强

一个应用要保证HA,往往需要N个服务器(N>1)提供服务,其中有M台master,N-M台slave。这样一台挂了,另外N-1台也能提供服务。所以,数据也会备份成N份散布在这些服务器上。现在的问题变成了,如何管理这N台服务器?如何在master节点失败的时候重新选择master?如何保证所有服务器存储的备份数据一致?

如果你碰到上面那些棘手的问题,zookeeper刚好可以帮到你:

上面列出的是官方提供的功能支持,还有很多其他功能等待挖掘。

当你的系统依赖zookeeper保证HA和一致性的时候,你肯定也好奇,zookeeper本身是如何保证这两个特性的。幕后功臣往往容易被忽视,其实它就是Zookeeper原子广播协议(Zab协议)。如果你了解过二阶段提交、paxos算法、raft算法等大名鼎鼎的分布式一致性算法,Zab肯定也不会陌生,因为他们要达到的目的相同,就是保证应用程序的HA和一致性。

为了读懂后面的内容,有些术语需要了解:

Zab的理论和实现并不完全一致。

实现是在理论的基础之上做了一些优化手段,这些优化是在zookeeper不断发展的过程中给加上的。我接下来的讲解,也是参照这篇论文,以zookeeper 3.3.3的版本的实现为准,并用自己的语言总结。

理论中的协议

随着系统启动或者恢复,会经历Zab协议中描述的如下四个阶段

之前我只是简述了一下理论中的协议,然而理想很骨感,有很多需要改进或者妥协的地方。下面我会一一阐明:

协议实现

了解了理想的骨感之后,我们回归现实。

真正apache zookeeper在实现上提出设想:优化leader选举,直接选出最新的Peer作为预备Leader,这样就能将阶段0和阶段1合并,减少网络上的开销和多流程的复杂性

图片

由图可知,代码实现上,协议被简化为三个阶段

Talk is cheap.Show me the Code

这时Linus说过的一句话,无论语言多么有力,只有代码才能真正展现作者的思想。之前我只是对是协议实现的三个阶段做了一番简述,只有代码才能真正拨开Zab协议外面那层迷雾。(为了不浪费篇幅,这里采用伪代码)


快速选举Leader阶段(FLE)


图片

首先初始化一些数据

如果当前节点处于选举状态,则它也会接到选票通知。它会从队列中不断轮询节点,以便获取选票信息(如果超时,则不断放松超时时间,直至上限)。根据轮询出来的发送节点的状态,来做相应的处理。


恢复阶段


图片

经过FLE,已经选出了日志中具有最新已提交的事务的节点作为预备Leader。下面就分Leader和Follower两个视角来介绍具体实现。

Leader视角

首先,更新lastZxid,将纪元+1,计数清零,宣布改朝换代啦。然后在每次接收到Follower的数据同步请求时,都会将自己lastZxid反馈回去,表示所有Follower以自己的lastZxid为准。接下来,根据具体情况来判断该如何将数据同步给Follower

当Follower完成同步时,会发送同步ack,当Leader收到Quorum ack时,表示数据同步阶段大功告成,进入最后的广播阶段。

Follower视角

通知Leader,表示自己希望能同步Leader中的数据。

当每个Follower完成上述的同步过程时,会发送ack给Leader,并进入广播阶段。


广播阶段


图片

进入到这个阶段,说明所有数据完成同步,Leader已经转正。开始zookeper最常见的工作流程:广播。

广播阶段是真正接受事务请求(写请求)的阶段,也代表了zookeeper正常工作阶段。所有节点都能接受客户端的写请求,但是Follower会转发给Leader,只有Leader才能将这些请求转化成事务,广播出去。这个节点一样有两个角色,下面还是按照这两个角色来讲解。

Leader视角:

Follower视角:

这篇文章没有介绍Zookeeper的使用,而是着重讲解它的核心协议Zab的实现。正如文中提及,Zab最早的设想和现在的实现并不相同,今日的实现是在Zookeeper不断发展壮大的过程中不断优化、改进而来的,也许早期的实现就是yahoo论文中构想的那样。罗马不是一日建成,任何人都不能指望一口吃个大胖子。如果Zookeeper刚开始就想着如何优化到极致,那反而会严重影响到这个项目本身的价值,因为它很可能还没面试就被淘汰。

We should forget about small e ciencies, say about 97% of the time: premature optimization is the root of all evil.

通过本文可以看出,过早优化是万恶之源。但是同时,一个好的程序员也不会忘记需要优化的那部分,他会定位相应的代码,然后针对性的修改。这也是zookeeper的开发者所做的。


标签:事务,Zookeeper,Zab,节点,选票,Follower,详解,阶段,Leader
来源: https://blog.51cto.com/u_15127568/2718237