2. ZAB协议内容 2.1 ZAB协议过程ZAB协议,Zookeeper Atomic Broadcast,Zookeeper
原子广播协议。是为分布式协调服务Zookeeper专门设计的一种支持崩溃恢复的原子广播协议 ,是Zookeeper保证数据一致性的核心算法。
当整个Zookeeper集群启动过程中,或者当 Leader 服务器出现网络中弄断、崩溃退出或重启等异常时,Zab协议就会进入崩溃恢复模式,选举产生新的Leader。
当选举产生了新的 Leader,同时集群中有过半的机器与该 Leader 服务器完成了状态同步(即数据同步)之后,Zab协议就会退出崩溃恢复模式,进入消息广播模式
集群中选举出Leader之后,后续节点加入集群会自动进入恢复模式:找到Leader服务器,并且完成数据同步。同步完成后,作为新的Follower一起参与到消息广播流程中。
2.2 ZAB协议状态切换当Leader出现崩溃退出或者机器重启,亦或是集群中不存在超过半数的服务器与Leader保存正常通信,Zab就会再一次进入崩溃恢复,发起新一轮Leader选举并实现数据同步。同步完成后又会进入消息广播模式,接收事务请求。
2.3 消息有序在整个消息广播中,Leader会将每一个事务请求转换成对应的 proposal 来进行广播,并且在广播事务Proposal 之前,Leader服务器会首先为这个事务Proposal分配一个全局单递增的唯一ID,称之为事务ID(即zxid),由于Zab协议需要保证每一个消息的严格的顺序关系,因此必须将每一个proposal按照其zxid的先后顺序进行排序和处理。
3. Zookeeper主节点同步数据的过程基于ZAB协议,Zookeeper实现了主从节点模式来同步数据,过程如图:
- Leader节点负责所有的写请求
- 数据更新完毕后,会向Follower节点发送ACK
- 有一半以上的 Follower 返回 Ack 信息就可以执行提交
ZAB协议的特性:
- Zab 协议需要确保那些已经在 Leader 服务器上提交(Commit)的事务最终被所有的服务器提交。
- Zab 协议需要确保丢弃那些只在 Leader 上被提出而没有被提交的事务。
ZAB 协议的消息广播过程使用的是一个原子广播协议,类似一个二阶段提交过程。对于客户端发送的写请求,全部由 Leader 接收, Leader 将请求封装成一个事务 Proposal,将其发送给所有 Follwer ,然后,根据所有 Follwer 的反馈,如果超过半数成功响应,则执行 commit *** 作。
消息广播过程:
- 客户端发起一个写 *** 作请求
- Leader 服务器将客户端的请求转化为事务 Proposal 提案,同时为每个 Proposal 分配一个全局的ID,即zxid
- Leader 服务器为每个 Follower 服务器分配一个单独的队列,然后将需要广播的 Proposal 依次放到队列中取,并且根据 FIFO 策略进行消息发送
- Follower 接收到 Proposal 后,会首先将其以事务日志的方式写入本地磁盘中,写入成功后向 Leader 反馈一个 Ack 响应消息
- Leader 接收到超过半数以上 Follower 的 Ack 响应消息后,即认为消息发送成功,可以发送 commit 消息
- Leader 向所有 Follower 广播 commit 消息,同时自身也会完成事务提交。Follower 接收到 commit 消息后,会将上一条事务提交
注意:
- zookeeper集群中为保证任何所有进程能够有序的顺序执行,只能是 Leader 服务器接受写请求,即使是 Follower 服务器接受到客户端的写请求,也会转发到 Leader 服务器进行处理,Follower只能处理读请求
- ZAB协议规定了如果一个事务在一台机器上被处理(commit)成功,那么应该在所有的机器上都被处理成功,哪怕机器出现故障崩溃
一旦 Leader 服务器出现崩溃或者由于网络原因导致 Leader 服务器失去了与过半 Follower 的联系,那么就会进入崩溃恢复模式。
崩溃恢复主要包括两部分:Leader选举 和 数据恢复
4.1 ZAB协议崩溃恢复原则进入崩溃恢复的情况:
- Leader 在复制数据给所有 Follwer 之后,还没来得及收到Follower的ack返回就崩溃
- Leader 在收到 ack 并提交了自己,同时发送了部分 commit 出去之后崩溃
ZAB协议崩溃恢复原则:
- ZAB 协议确保丢弃那些只在 Leader 提出/复制,但没有提交的事务
- ZAB 协议确保那些已经在 Leader 提交的事务最终会被所有服务器提交
所以根据ZAB协议崩溃恢复原则,需要保证选举出来的Leader需要满足以下条件:
- 新选举出来的 Leader 不能包含未提交的事务(Proposal), 即新选举的 Leader 必须都是已经提交了 Proposal 的 Follower 服务器节点
- 新选举的 Leader 节点中含有最大的事务id(zxid) ,避免 Leader 服务器检查 Proposal 的提交和丢弃工作。
- 当崩溃恢复之后,需要在正式工作之前(接收客户端请求),Leader 服务器首先确认事务是否都已经被过半的 Follwer 提交了,即是否完成了数据同步,目的是为了保持数据一致。
- Leader 服务器需要确保所有的 Follower 服务器能够接收到每一条事务的 Proposal ,并且能将所有已经提交的事务 Proposal 应用到内存数据中。等到 Follower 将所有尚未同步的事务 Proposal 都从 Leader 服务器上同步过并且应用到内存数据中以后,Leader 才会把该 Follower 加入到真正可用的 Follower 列表中。
ZXID 的生成:
ZAB 协议的事务编号 ZXID,由64 位的数字构成。
低 32 位可以看作是一个简单的递增的计数器,针对客户端的每一个事务请求,Leader 都会产生一个新的事务 Proposal 并对该计数器进行 + 1 *** 作。
高 32 位则代表了 Leader 服务器上取出本地日志中最大事务 Proposal 的 ZXID,并从该 ZXID 中解析出对应的 epoch 值(leader选举周期),当一轮新的选举结束后,会对这个值加一,并且事务id又从0开始自增。
高 32 位代表了每代 Leader 的唯一性,低 32 代表了每代 Leader 中事务的唯一性。同时,也能让 Follwer 通过高 32 位识别不同的 Leader。
基于以上策略:当 Follower 连接上 Leader 之后,Leader 服务器会根据自己服务器上最后被提交的 ZXID 和 Follower 上的 ZXID 进行比对,比对结果要么回滚(回滚到一个确实已经被集群中过半机器 Commit 的最新 Proposal),要么和 Leader 同步。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)