概述
1、zab协议的作用:zab协议是专门为zookeeper设计的一套用于 原子广播和 崩溃恢复的协议。
2、ZAB协议基于2PC算法(两阶段提交)算法来进行设计,并利用了paxos算法进行了改进。
原子广播
1、原子广播机制的作用:
保证数据的一致性。连接任意一个zk服务器,获取到的数据都是一样的。
2、设计
原子广播基于2PC算法来进行设计,并加入了 过半性来进行改进。
3、什么是2PC
2PC,两阶段提交,这个算法把请求拆分成了两个阶段,请求-提交或者是请求-终止。2PC算法的核心思想是一票否决权(最要干活的节点响应了一个no,那么这个请求就不会被提交执行)
2PC的优缺点很明显:有点是实现简单,发出器多少个请求,就需要收道多少个请求,只要有一个不干,那这件事就不干了。
缺点是太过于保守,严格,受网络的影响比较大。一个节点不干整个集群就无法处理这个请求了,所以原子广播在2PC的基础之上增加了过半性加以改进。
具体的过程可以分成以下几个部分:
①请求阶段:协调者(2pc协议中叫协调者,也就是zk中的leader)收到请求之后,将请求分发给每一个参与者(zk中的follower),等待参与者的反馈信息
②提交阶段:协调者收到了所有参与者返回的yes,那么说明这个请求可以执行,协调者就会命令所有节点执行这个请求
③终止阶段:提交之后也有可能进入终止阶段。如果协调者没有收到所有参与者返回yes,就认为这个请求不能执行,会要求所有的节点撤销刚才的请求。有可能是参与者返回了一个no,也有可能是网络原因协调者没有收到参与者返回的yes。不管什么情况,请求都不会被执行。
4、什么是原子广播
也是leader收到请求以后,会向follower询问是否能够执行操作;此时不需要所有的参与者都返回yes(因为这个条件太严格了),只需要等到过半的节点能够返回yes,就让follower执行这个请求。
leader收到请求以后,会现在自己的日志中记录;记录成功以后,leader将请求放到一个 队列中分发给每一个follower
follower在收到队列以后,也是先记录到本地日志当中。
如果记录成功就给leader返回yes,如果记录失败就给leader放回no
leader根据确认过半的原则确定该指令执行或者不执行
不管是leader还是follower,在收到请求的时候,都是先往自己的日志里面写。如果没有配置log目录的话,日志文件在tmp目录下的version-2文件夹下面。客户端发出一个写操作,就会添加一条记录到日志文件中。
follower也是一样的 ,记录成功返回yes,记录失败返回no
假如说,某个follower已经给leader返回了no,表示无法执行请求,但是leader还是让执行了这条指令怎么办?
follower会向leader发送一个请求,请求重新获取刚才的信息并重新记录重新执行 (这个节点会尝试着重新记录一下)
为什么follower有可能会返回no给leader?
当follower的日志记录失败的时候就会返回no给leader,有以下几种情况:
1、网络问题,例如产生数据丢失导致follower没有收到请求 (一直产生网络波动的概率很小,如果一直没有收到,就会一直循环请求leader发送)
2、磁盘空间已满,磁盘损坏
3、follower在记录日志的时候发现日志被占用
拓展:查看日志文件
进入zookeeper的解压目录,将zookeeper-3.4.8.jar拷贝至version-2目录下
进入lib目录,将slf4j-api-1.6.1.jar 也拷贝到version-2目录下
进入version-2目录执行以下命令
java -cp .:zookeeper-3.4.8.jar:slf4j-api-1.6.1.jar org.apache.zookeeper.server.LogFormatter log.500000001
日志中就是记录了zk节点上发生的一些操作,什么事件,什么session,执行了什么操作等
崩溃恢复
1、当集群中的leader宕机或者丢失之后,Zookeeper集群不会停止对外服务而是会重新选举出一个新的leader
2、作用:避免单点故障
3、每一次选举出来的leader都会分配一个全局递增的id,称之为epochid
4、在Zookeeper集群中,事务id由64位二进制数字(16位十六进制)组成,其中 高32位对应了epochid,低32位对应了实际的事务id
5、当一个节点重新连入集群的时候,节点会先找到当前节点中的最大事务id,然后给leader发请求,== 比较最大事务id==
,看自己落后多少。leader在收到请求比较之后,如果发现最大事务id不一致,那么leader就会将中间差出来的事务放到一个队列中(leader向follower发请求用的都是队列)发送给follower,要求这个follower恢复到和整个集群相同的水平。这个follower在恢复期间不接收新的操作。