Zookeeper 深入进阶 —— ZAB 协议

Zookeeper 深入进阶 —— ZAB 协议

概念

在深入了解 zookeeper 之前,很多同学可能会认为 zookeeper 就是 paxos 算法的一个实现。但事实上,zookeeper 并没有完全采用 paxos 算法,而是使用了一种称为 Zookeeper Atomic Broadcast (ZAB,zookeeper 原子消息广播协议)的协议作为其数据一致性的核心算法。

ZAB 协议并不像 Paxos 算法是一种通用的分布式一致性算法,它是一种特别为 zookeeper 专门设计的一种支持崩溃恢复的原子广播协议

在 zookeeper 中,主要就是依赖ZAB协议来实现分布式数据的一致性,基于该协议,zookeeper实现了一种主备模式的系统架构来保持集群各副本之间数据的一致性。表现形式就是使用一个单一的主进程来接收并处理客户端的所有事务请求,并采用ZAB的原子广播协议,将服务器数据的状态变更以事务 Proposal 的形式广播到所有的副本进程中。

ZAB协议的主备模型架构保证了同一时刻集群中只能有一个主进程来广播服务器的状态变更,因此能够很好地处理客户端大量的并发请求。但是,也要考虑到主进程在任何时候都有可能出现崩溃退出或者重启,因此,ZAB协议还需要做到当前主进程当出现异常情况时,集群还能正常工作。

ZAB 核心

ZAB 协议的核心是定义了 对于那些会改变 zookeeper 服务器数据状态的事务请求的处理方式:

所有的事务必须有一个全局唯一的Leader服务器来协调处理

Leader 服务器负责将客户端事务请求转化成一个事务 Proposal (提议),并将该 Proposal 分发给集群中所有的 Follower 服务器,之后 Leader 服务器需要等待 Follower 服务器的反馈,一旦超过半数的 Follower 服务器进行正确的反馈后,那么 Leader 服务器会向所有的 Follower 发送 Commit 消息,将 Proposal 提交

在这里插入图片描述

ZAB 协议介绍

ZBA协议包括两种基本的模式:崩溃恢复消息广播

崩溃恢复模式

当整个服务框架启动过程中,或者是 Leader 服务器出现网络中断、崩溃退出或重启等异常情况时,ZAB协议就会进入崩溃模式,同时选举产生新的 Leader 服务器。

当选举产生新的 Leader 服务器,同时集群中已经有过半的机器与该 Leader 服务器完成了数据同步之后,ZAB 协议就会退出崩溃模式

消息广播模式

当集群中已经有过半的 Follower 服务器完成了 Leader 服务器的状态同步,那么整个服务框架就可以进入消息广播模式。

当一台同样遵守ZAB协议的服务器启动后加入到集群中,如果此时集群中已经存在一个 Leader 服务器在负责进行消息广播,那么新加入的服务器会自觉进入数据恢复模式:找到Leader 所在的服务器,并与其进行数据同步,然后一起参加到消息广播流程中。

zookeeper 只允许唯一的一个 Leader 服务器来进行事务请求处理,Leader 服务器在接收到客户端的事务请求后,会生成对应的事务提议并发起一轮广播协议,而如果集群中的其他机器收到客户端的事务请求后,那么这些非 Leader 服务器会首先将这个请求转发给 Leader 服务器。

消息广播过程

ZAB 协议的消息广播过程使用原子广播协议,类似于一个两阶段提交过程。针对客户端的事务请求,Leader 服务器会为其生成对应的事务 Proposal,并将其发送给集群中其余的机器,然后再分别收集各自的选票,最后进行事务提交。

在这里插入图片描述

在ZAB的两阶段提交过程中,移除了中断逻辑,所有的 Follower 服务器要么正常反馈 Leader 提出的事务 Proposal,要么就抛弃 Leader 服务器。同时,ZAB 协议将两阶段提交中的中断逻辑移除意味着我们可以在过半的 Follower 服务器反馈 ACK 之后就开始提交事务了,而不需要等待集群中所有的 Follower 都反馈。

但是i这种简化的两阶段提交中,无法处理因 Leader 服务器崩溃而带来数据不一致的问题,因此,ZAB 采用了崩溃恢复模式来解决此问题。

另外,整个消息广播协议是基于局哟与 FIFO 特性的TCP协议来进行网络通信的,因此能够保证消息广播过程中消息接收与发送的顺序性。

在整个消息广播过程中,Leader 服务器会为每个事务请求生成对应的 Proposal 来进行广播,并且在广播事务 Proposal 之前,Leader 服务器会首先为这个事务 Proposal 分配一个全局单调递增的唯一ID,称之为 事务ID(ZXID),由于ZAB协议需要保证每个消息严格的因果关系,因此必须将每个事务按照其ZXID的先后顺序来进行处理。

具体过程:

在消息广播过程中,Leader 服务器会为每一个 Follower 服务器都各自分配一个单独的队列,然后将需要广播的事务 Proposal 依次放入这些队列中去,并根据 FIFO 策略进行消息发送。

每一个 Follower 服务器在接收到这个事务之后,都会首先将其以事务日志的形式写入本地磁盘中,并且在成功写入后反馈 Leader 一个 ACK 响应。

当 Leader 服务器接收到超过半数 Follower 的 ACK 响应后,就会广播一个 Commit 消息给所有的 Follower 服务器通知进行事务提交,同时 Leader 自身也会完成事务的提交

每个 Follower 接收到 Commit 消息后,也会完成事务提交

崩溃恢复过程

ZAB 协议的这个基于原子广播协议的消息广播过程,在正常情况下运行非常良好,但是一旦 Leader 服务器出现崩溃,或者由于网络原因导致 Leader 服务器失去了与过半 Follower 的联系,那么就会进入崩溃恢复模式。

在ZAB协议中,为了保证程序的正确运行,整个恢复过程结束后需要选举出一个新的 Leader 服务器。因此,ZAB协议需要一个高效且可靠的Leader 选举算法从而保证能够快速地选举出新的 Leader,同时,Leader 选举算法不仅仅需要让 Leader 自身知道已经被选举为 Leader,同时还需要让集群中的所有的其他机器也能快速地感知到选举产生出来的新的 Leader 服务器。

基本特性:

根据上面的内容,我们了解到,ZAB 协议规定了如果一个事务 Proposal 在一台机器上被处理成功,那么应该在所有的机器上都被处理成功,哪怕机器出现故障崩溃。接下来我们看看在崩溃恢复过程中,可能会出现的两个数据不一致的隐患及针对这些情况ZAB协议所需要保证的特性。

ZAB 协议需要确保那些已经在 Leader 服务器上提交的事务最终被所有服务器都提交。

假设一个事务在 Leader 服务器上被提交了,并且已经得到过半 Follower 服务器的 ACK 反馈,但是它将 Commit 消息发送给所有 Follower 机器之前,Leader 服务器挂了,如图所示:

在这里插入图片描述

图中的消息C2就是一个典型的例子:

在集群正常运行过程中的某一个时刻,Server1是Leader服务器,其先后广播了消息P1、P2、C1、P3和C2,当 Leader 将消息C2 (C2是 Commit Of Proposal2的缩写)发出后就立即崩溃退出了。针对这种情况,ZAB协议就需要确保事务 Proposal2 最终能够在所有的服务器上都被提交成功,否则将出现数据不一致。

ZAB 协议需要确保丢弃那些只在 Leader 服务器上被提出的事务

如果在崩溃恢复过程中出现一个需要被丢弃的提案,那么在崩溃恢复结束后需要跳过该事务 Proposal,如图所示

在这里插入图片描述

在所示的集群中,假设初始的 Leader 服务器 Server1 提出了一个事务 P3之后就崩溃退出了,从而导致集群中的其他服务器都没有收到这个事务。于是,当 Server1 恢复过来再次加入集群时,ZAB协议需要确保丢弃P3这个事务。

结合上面提到的这两个崩溃恢复过程中需要处理的特殊情况,就决定了 ZAB 协议必须设计这样一个 Leader 选举算法:能确保提交已经被 Leader 提交的事务 Proposal ,同时丢弃已经被跳过的事务 Proposal 。针对这个要求,如果让 Leader 选举算法能够保证新选举出来的 Leader 服务器拥有集群中所有机器最高编号(即ZXID最大)的事务Proposal,那么就可以保证这个新选举出来的 Leader 一定具有所有已经提交的提案。更为重要的是,如果让具有最高编号事务 Proposal 的机器来成为 Leader ,就可以省去 Leader 服务器检查 Proposal 的提交和丢弃工作的这一步操作了。

数据同步

完成 Leader 选举之后,在正式开始工作(即接收客户端的事务请求,然后提出新的提案)之前,Leader 服务器会首先确认事务日志中的所有 Proposal 是否都已经被集群中的过半机器提交了,即是否完成数据同步。下面我们来看看 ZAB 协议的数据同步过程:

所有正常运行的服务器,要么成为 Leader,要么成为 Follower 并和 Leader 保持同步。Leader 服务器需要确保所有的 Follower 服务器能够接收到每一条事务 Proposal,并且能够正确地将所有已经提交了的事务 Proposal 应用到内存数据库中去。具体的,Leader 服务器会为每一个 Follower 服务器都准备一个队列,并将那些没有被各 Follower 服务器同步的事务以 Proposal 消息的形式逐个发送给 Follower 服务器,并在每一个 Proposal 消息后面紧接着再发送一个 Commit 消息,以表示该事务已经提交。等到 Follower 服务器将所有未同步的事务都从 Leader 服务器同步过来并成功应用到本地数据库中,Leader 服务器就会将该 Follower 服务器加入真正可用 Follower 列表,并开始之后的其他流程。

运行时状态分析

在ZAB 协议的设计中,每个进程都有可能处于如下三种状态:

  1. LOOKING:Leader 选举状态
  2. FOLLOWING:Follower 服务器和 Leader 服务器保持同步状态
  3. LEADING:Leader 服务器作为主进程领导状态

所有进程初始状态都是 LOOKING 状态,此时不存在 Leader,接下来,进程会视图选举出一个新的 Leader ,之后,如果发现已经选举出新的 Leader 了,那么它就会切换到 FOLLOWING 状态,并开始和 Leader 保持同步,处于 FOLLOWING 状态的进程称为 Follower,处于 LEADING 状态的进程成为 Leader。

当 Leader 崩溃或者放弃领导地位时,其余的 Follower 进程就会转换到 LOOKING 状态开始新一轮的 Leader 选举。

一个 Follower 只能和一个 Leader 保持同步,Leader 进程和所有的 Follower 进程之间都通过心跳检查机制来感知彼此的情况。若 Leader 能够在超时时间内正常收到心跳检测,那么 Follower 就会一直与该 Leader 保持连接,而如果在指定时间内 Leader 无法从过半的 Follower 进程那里接收到心跳检测,或者TCP连接断开,那么 Leader 会放弃当前周期的领导,并转换到 LOOKING 状态,其他的Follower 也会选择放弃这个 Leader ,同时切换到 LOOKING 状态,之后开启新的一轮Leader 选举

ZAB 与 Paxos 的联系和区别

联系:

① 都存在一个类似于 Leader 进程的角色,由其负责协调多个 Follower 进程的运行。

② Leader 进程都会等待超过半数的Follower做出正确的反馈后,才会将一个提议进行提交。

③ 在 ZAB 协议中,每个 Proposal 都包含了一个 epoch 值,用来代表当前的 Leader 周期,在 Paxos 算法中,同样存在一个这样的标识,名字为 Ballot。

区别:

Paxos 算法中,新选举产生的主进程会进行两个阶段的工作,第一阶段称为读阶段,新的主进程和其他进程通信来收集主进程提出的提议,并将它们提交。第二阶段称为写阶段,当前主进程开始提出自己的提议。

ZAB 协议在 Paxos 基础上添加了同步阶段,此时,新的 Leader 会确保 存在过半的 Follower 已经提交了之前的 Leader 周期中的所有事务 Proposal。这一同步阶段的引入,能够有效地保证 Leader 在新的周期中提出事务 Proposal之前。所有的进程都已经完成了对之前所有事务 Proposal 的提交。

总的来说,ZAB 协议和 Paxos 算法的本质区别在于,两者的设计目标不太一样,ZAB 协议主要用于构建一个高可用的分布式数据库主备系统,而 Paxos 算法则用于构建一个分布式的一致性状态及系统。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值