了解 ZAB协议
作者:互联网
- 1. ZAB协议
ZAB (Zookeeper Atomic BroadCast 简称),zk原子消息广播协议,专为zookeeper设计的一种支持崩溃恢复的原子广播协议,在zookeeper中,主要依赖ZAB协议来实现分布式数据一致性。
zookeeper 使用一个单一主进程来接收并处理客户端的所有写请求当服务器数据状态发生变更,集群采用ZAB协议,以事务提案Proposal 的形式广播到所有的副本进程上。ZAB协议能够保证一个全局的变更序列,即可以为每一个事务分配一个全局的递增编号 xid。
当zookeeper客户端连接到zookeeper集群的一个节点后,若客户端提交的是读请求,那当前节点就直接根据自己保存的数据对其进行响应;如果是写请求且当前节点不是leader ,那么节点就会将该请求转发给leader 处理,leader会以提案的方式广播该写操作,只要超过半数节点通过提案,则该写操作就会被提交。然后leader 会再次广播给其他所有订阅者,通知它们同步数据。
2.三类角色
为了避免zookeeper单点问题,zk是以集群的形式出现的。zk集群中的角色主要有三类:
- leader:处理读写请求
- follower:可以直接处理客户端的读请求,并向客户端响应。但不会处理写请求,只会将写请求转发给leader来处理;对leader发起的提案有表决权,同步leader中的事务处理结果,leader选举过程的参与者,具有选举权和别选举权
- observer:可以理解为不参与leader选举的follower,在leader选举过程中没有选举权和被选举权,同时对于leader的提案没有表决权。只是用来协助follower处理更过的读请求。
这三类角色在不同情况下有不同的名称: - learner:学习者,即要从leader中同步数据的server,是follower和observer的组合
- quorumServer:法定服务器,法定主机。在集群正常服务状态下,具有表决权的服务器。在leader选举过程中,具有选举权与被选举权的服务器,成为 participant
4.三个数据
在ZAB中有三个重要数据:
- zxid:为一个64位长度的long 类型,高32位表示epoch,低32位表示 xid
- epoch:每个leader选举结束后都会产生一个新的epoch,并通知集群中其他server,包含follower和observer
- xid:事务id,流水号
5.四种状态
zk集群中的每台主机,在不同阶段会处于不同的状态,每台主机具有四种状态。
- LOOKING:选举状态
- FOLLOWING:follower的正常工作状态
- OBSERVING:observer的正常工作状态
- LEADING:leader的正常工作状态
6.同步模式与广播模式
(1) 初始化广播
当完成leader选举后,此时的leader还只是准leader,要经过初始化同步后才能成为真正的leader。
具体过程:
- 为了保证leader向learner发送提案的有序,leader 会为每个learner 服务器准备一个队列
- leader 将那些没有被各个learner同步的事务封装为 Proposal
- leader 将这些Proposal逐条发给各个learner,并在每个Proposal 后紧跟一个COMMIT消息,表示该事务已被提交,learner可以直接接收并执行
- learner 接受来自于leader的Proposal,并将其更新到本地
- 当learner 更新成功后,会向准leader发送ACK消息
- 当leader服务器在收到来自learner的ack后就会将该learner加入到真正可用的follower列表或observer列表。没有反馈ack,或反馈了但leader没有收到的learner,leader不会将其加入到相应列表
(2) 消息广播算法
当集群中的learner完成了初始化状态同步,那么整个zk集群就进入到正常工作模式了。如果集群中learner收到客户端的事务请求,那么learner就将请求转发给leader服务器,然后执行如下过程:
1.leader接收到事务请求后,为事务赋予全局唯一的64位自增id,即zxid,通过zxid的大小比较即可实现事务的有序性管理,然后将事务封装为一个Proposal。
2.leader根据follower 列表获取到所有follower,然后将Proposal 通过这些follower队列将提案发送给各个follower。
3.当follower 接收到提案后,会先将提案的zxid与本地记录的事务日志中的最大的zxid进行比较,如果当前提案的zxid大于最大zxid,则将当前提案记录到本地事务日志中,并向leader返回ack
4.当leader 接收到过半的ack后,leader 就会向所有follower 的队列发送 COMMIT消息,向所有observer队列发送 Proposal。
5.当follower 收到COMMIT消息,就将日志中的事务正式更新到本地,当observer 收到Proposal后,直接将事务更新到本地。
6无论是follower 还是observer,在同步完成后都需要向leader发送成功 ACK。
7.恢复模式的三个原则
- leader 的主动出让原则
若集群中leader收到的follower心跳数量没有过半,此时leader会自认为自己与集群的连接已经出现问题,就会主动修改自己状态为 LOOKING,去查找新的leader,而其他server 由于有过半的主机认为已经丢失leader,会发起新的leader选举,选出新的leader。 - 已被处理过的消息不能丢原则
当leader收到超过半数follower 的ACK后,就向各个follower 广播COMMIT消息,批准各个server 执行该写操作事务。当各个Server 在接收到leader 的COMMIT 消息后就会在本地执行该写操作,然后会向客户端响应写操作成功。但是如果在非全部follower 收到COMMIT之前leader 挂了,这就导致:部分server 已经执行了该事物,而部分server 都不知道有这回事。当新的leader被选举出,集群经过恢复模式后需要保证所有server 上都执行了那些已经被部分server执行过的事务。 - 被丢弃的消息不能再现原则
当在leader 新事物已经通过,已经将事务更新到本地,但所有follower 还没收到COMMIT ,此时leader 宕机,那么所有的follower 都不知道Proposal 的存在。当新leader选举出来,集群进入正常服务状态,之前挂了的leader 重新启动并注册成为 follower,若其他follower 都不知道的Proposal 还保留在这个主机,那么该主机的数据就比其他主机多出数据,导致整个系统状态的不一致了。所以该Proposal应该被丢弃,类似这样应该被丢弃的事务,是不能再次出现在集群中的,应该被清除。
标签:协议,事务,learner,ZAB,follower,了解,集群,Proposal,leader 来源: https://blog.csdn.net/manong115/article/details/116352874