Leader是Zk中最重要的技术之一,也是保证分布式数据一致性的关键所在。
所谓“过半性”就是指大于集群机器数量的一半,即大于或等于(n/2+1)
首先需要先讲讲服务器启动时期的Leader选举
Leader选举的条件是集群中最少有两台服务器,这里以3台机器为例。
在服务器集群初始化阶段,当有一台服务器(假设这台集群的myid 为1,因此称其为Server1)启动的时候,它是无法进行选举的,当第二台集群(myid 2 | Server2)也启动后,此时这两台机器已经能够互相通信,每台机器都视图找到一个Leader,于是便进入了Leader选举流程。
1、每个Server会发出一个投票
由于是初始情况,因此对于Server1和Server2来说,都会将自己作为Leader来进行投票,每次投票包含的最基本的元素包括:所推举的服务器的myid和ZXID(最大事务ID),我们以(myid,ZXID)的形式来表示。因为是初始化节点,因此都会投给自己,即Server1的投票为(1,0),Server2为(2,0),然后各自将这个投票发给集群中的其他所有机器
2、接收来自各个服务器的投票
集群中的每个服务器在接收到投票后首先会判断该投票的有效性,包括检查是否是本轮投票、是否来自LOOKING状态(寻找Leader状态)的服务器。
3、处理投票
针对每一个偷拍哦。服务器都需要将别人的投票和自己的投票进行PK,PK的规则如下。
4、统计投票
每次投票后,服务器都会统计所有投票,判断是否有过半的机器接收到相同的投票信息。对应Server1和Server2服务器来说,都统计出集群中已经有两台机器接受了(2,0)这个投票信息。满足过半性,即认为已经选出了Leader。
5、改变服务器状态
一旦确定了Leader,每个服务器就会更新自己的状态:如果是Follower,则变更为FOLLOWING,如果是Leader,那么就变更为LEADING。
服务器运行期间的Leader选举
在Zookeeper集群正常运行过程中,一旦选出一个Leader,那么所有的服务器 的集群角色都不会再发生变化,也就是说,Leader服务器将一直作为集群的Leader,除非Leader服务器挂掉了,那么整个集群将暂时无法对外提供服务,而是进入新一轮的Leader选举,与服务器启动使其的选举过程是一致的。
假设Server2挂了
1、变更状态
当Leader挂了之后,余下非Observer服务器都会将自己的服务器状态变更为LOOKING,然后开始进入Leader选举过程。
2、每个Server会发出一个投票
由于是运行期间,因此每个服务器上的ZXID可能不同我们假设Server1的ZXID为123,而Server3的ZXID为122,在第一轮投票中,Server1和Server3都会投给自己,即分别产生投票(1,123),(3,122),然后各自将这个投票发给集群中所有机器。
3、接收各个服务器的投票
4、处理投票
对于投票的处理,和上面提到的服务器启动期间的处理规则是一致的,在这个情境下Server1的ZXID为123,Server3的ZXID为122,显然Server1会成为Leader
5、统计投票
6、改变服务器状态
ZAB协议是为分布式协调服务ZK专门设计的一种支持崩溃恢复和原子广播的协议。
在ZK中,主要依赖ZAB协议来实现分布式数据一致性,基于该协议,Zookeeper实现了一种主备模式的系统架构来保持集群中各个副本之间数据的一致性。具体的,Zk使用一个单一的主进程来接受并处理客户端的所有事务请求。
**ZAB协议的核心**是定义了对于那些会改变ZK服务器数据状态的事务请求的处理方式,即
所有事务请求必须由一个全局唯一的服务器来协调处理,这样的服务器被称为leader服务器,而余下的其他
服务器则称为follower服务器,leader服务器负责将一个客户端事务请求转换成一个事务Proposal(提
议),并将该Proposal分发给集群中所有的Follower服务器,之后leader服务器需要等待所有的follower服
务 器的ack,一旦超过半数的follwer服务器进行了正确的反馈之后,那么leader就会再次向所有的follower
服务器分发Commit消息,要求其向前一个Proposal进行提交.
ZAB协议的两种基本的模式:
消息广播
ZAB协议的消息广播过程使用的是一个原子广播协议,类似于一个二阶段提交过程。针对客户端的事务请求Leader服务器会为其生成对应的事务Proposal(提议),并将其发送给集群中其余所有的机器,然后在分别收集各自的选票,最后进行事务提交。
在ZAB协议的二阶段提交过程中,溢出了中断逻辑,所有的Follower服务器要么正常反馈Leader提出的事务Proposal,要么就抛弃Leader服务器。同时ZAB协议将二阶段提交中的中断逻辑移除意味着我们可以在过半的Follower服务器已经反馈ACK之后就开始提交事务Proposal了,而不需要等待集群中所有的Follwer服务器都反馈响应。但是,这种简化了的二阶段提交模型下,**是无法处理Leader服务器崩溃退出而带来的数据不一致问题的,**因此在ZAB协议中添加了崩溃恢复模式来解决这个问题。
Zookeeper中消息广播的具体步骤如下:
特性:Leader服务器与每一个Follwer之间都有一个单独的队列进行消息发送与接收,使用队列消息可以做到异步解耦。Leader和Follower之间只要往队列中发送了消息即可。如果使用同步方式容易引起阻塞,性能上要下降很多。
整个消息广播协议时基于具有FIFO特性的TCP协议来进行网络通信的,因此能够容易的保证消息广播过程中消息接收与发送的顺序性。
崩溃恢复:当ZAB协议在基于原子广播协议的消息广播过程中,在正常情况下运行非常良好,但是一旦Leader服务器出现崩溃,或者由于网路原因导致Leader服务器是去了与过半Follower服务器的联系,那么就会进入崩溃恢复模式。在ZAB协议中,为了保证程序的正确运行,整个恢复过程结束后需要选举出一个新的Leader服务器。
ZAB协议崩溃恢复要求满足如下2个要求
根据上述要求,新选举出来的leader不能包含未提交的Proposal,即新选举的leader必须都是已经提交了Proposal的Follower服务器节点,同时,新选举的Leader节点中含有最大事务ID(ZXID),这样做的好处就是可以避免了leader服务器检查Proposal的提交和丢弃工作。
Leader服务器发生崩溃时的如下情景:
数据同步过程:
当崩溃恢复选举完leader之后就要进行数据同步过程。
以上ZXID中的epoch也能避免Zookeeper集群中的脑裂,当崩溃恢复之后,可能产生多个leader,follower只会执行epoch最大的leader的Proposal和Commit消息,避免了脑裂产生的问题。