写在开始:这是我找到一篇比较好的博客,转载到这来进行备份原文参考: Zookeeper ZAB 协议分析

前言

ZAB 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。

Atomic broadcast protocol

ZAB 是 Zookeeper 原子广播协议的简称,下面我们来讨论协议的内容,注意:理论与实现是有区别的,如果你对协议的理论不感兴趣,可以直接跳过看实现。

问题的提出

Zookeeper 客户端会随机连接到 Zookeeper 集群的一个节点,如果是读请求,就直接从当前节点中读取数据;如果是写请求,那么节点就会向 leader 提交事务,leader 会广播事务,只要有超过半数节点写入成功,该写请求就会被提交(类 2PC 协议)。
那么问题来了:

  • 主从架构下,leader 崩溃,数据一致性怎么保证?
  • 选举 leader 的时候,整个集群无法处理写请求的,如何快速进行 leader 选举?
    带着这两个问题,我们来看看 ZAB 协议是如何解决的。

ZAB 的四个阶段

  • quorum:集群中超过半数的节点集合

ZAB 中的节点有三种状态

  • following:当前节点是跟随者,服从 leader 节点的命令
  • leading:当前节点是 leader,负责协调事务
  • election/looking:节点处于选举状态

代码实现中多了一种:observing 状态,这是 Zookeeper 引入 Observer 之后加入的,Observer 不参与选举,是只读节点,跟 ZAB 协议没有关系

节点的持久状态

  • history:当前节点接收到事务提议的 log
  • acceptedEpoch:follower 已经接受的 leader 更改年号的 NEWEPOCH 提议
  • currentEpoch:当前所处的年代
  • lastZxid:history 中最近接收到的提议的 zxid (最大的)

在 ZAB 协议的事务编号 Zxid 设计中,Zxid 是一个 64 位的数字,其中低 32 位是一个简单的单调递增的计数器,针对客户端每一个事务请求,计数器加 1;而高 32 位则代表 Leader 周期 epoch 的编号,每个当选产生一个新的 Leader 服务器,就会从这个 Leader 服务器上取出其本地日志中最大事务的ZXID,并从中读取 epoch 值,然后加 1,以此作为新的 epoch,并将低 32 位从 0 开始计数。
epoch:可以理解为当前集群所处的年代或者周期,每个 leader 就像皇帝,都有自己的年号,所以每次改朝换代,leader 变更之后,都会在前一个年代的基础上加 1。这样就算旧的 leader 崩溃恢复之后,也没有人听他的了,因为 follower 只听从当前年代的 leader 的命令。*

Phase 0: Leader election(选举阶段)

节点在一开始都处于选举阶段,只要有一个节点得到超半数节点的票数,它就可以当选准 leader。只有到达 Phase 3 准 leader 才会成为真正的 leader。这一阶段的目的是就是为了选出一个准 leader,然后进入下一个阶段。
协议并没有规定详细的选举算法,后面我们会提到实现中使用的 Fast Leader Election。

Phase 1: Discovery(发现阶段)

在这个阶段,followers 跟准 leader 进行通信,同步 followers 最近接收的事务提议。这个一阶段的主要目的是发现当前大多数节点接收的最新提议,并且准 leader 生成新的 epoch,让 followers 接受,更新它们的 acceptedEpoch

一个 follower 只会连接一个 leader,如果有一个节点 f 认为另一个 follower p 是 leader,f 在尝试连接 p 时会被拒绝,f 被拒绝之后,就会进入 Phase 0。

Phase 2: Synchronization(同步阶段)

同步阶段主要是利用 leader 前一阶段获得的最新提议历史,同步集群中所有的副本。只有当 quorum 都同步完成,准 leader 才会成为真正的 leader。follower 只会接收 zxid 比自己的 lastZxid 大的提议。

Phase 3: Broadcast(广播阶段)

到了这个阶段,Zookeeper 集群才能正式对外提供事务服务,并且 leader 可以进行消息广播。同时如果有新的节点加入,还需要对新节点进行同步。

值得注意的是,ZAB 提交事务并不像 2PC 一样需要全部 follower 都 ACK,只需要得到 quorum (超过半数的节点)的 ACK 就可以了。

协议实现

协议的 Java 版本实现跟上面的定义有些不同,选举阶段使用的是 Fast Leader Election(FLE),它包含了 Phase 1 的发现职责。因为 FLE 会选举拥有最新提议历史的节点作为 leader,这样就省去了发现最新提议的步骤。实际的实现将 Phase 1 和 Phase 2 合并为 Recovery Phase(恢复阶段)。所以,ZAB 的实现只有三个阶段:

  • Fast Leader Election
  • Recovery Phase
  • Broadcast Phase

Fast Leader Election

前面提到 FLE 会选举拥有最新提议历史(lastZixd最大)的节点作为 leader,这样就省去了发现最新提议的步骤。这是基于拥有最新提议的节点也有最新提交记录的前提。

成为 leader 的条件

  1. 选epoch最大的
  2. epoch相等,选 zxid 最大的
  3. epoch和zxid都相等,选择server id最大的(就是我们配置zoo.cfg中的myid)
    节点在选举开始都默认投票给自己,当接收其他节点的选票时,会根据上面的条件更改自己的选票并重新发送选票给其他节点,当有一个节点的得票超过半数,该节点会设置自己的状态为 leading,其他节点会设置自己的状态为 following。

选举过程

Recovery Phase (恢复阶段)

这一阶段 follower 发送它们的 lastZixd 给 leader,leader 根据 lastZixd 决定如何同步数据。这里的实现跟前面 Phase 2 有所不同:Follower 收到 TRUNC 指令会中止 L.lastCommittedZxid 之后的提议,收到 DIFF 指令会接收新的提议。

  • history.lastCommittedZxid:最近被提交的提议的 zxid
  • history:oldThreshold:被认为已经太旧的已提交提议的 zxid

总结

经过上面的分析,我们可以来回答开始提到的两个问题

  • 主从架构下,leader 崩溃,数据一致性怎么保证?

leader 崩溃之后,集群会选出新的 leader,然后就会进入恢复阶段,新的 leader 具有所有已经提交的提议,因此它会保证让 followers 同步已提交的提议,丢弃未提交的提议(以 leader 的记录为准),这就保证了整个集群的数据一致性。

  • 选举 leader 的时候,整个集群无法处理写请求的,如何快速进行 leader 选举?

这是通过 Fast Leader Election 实现的,leader 的选举只需要超过半数的节点投票即可,这样不需要等待所有节点的选票,能够尽早选出 leader。
这篇文章是根据我对 ZAB 协议的理解写成的,如果觉得有些细节没有讲清楚,可以看后面的参考资料,我主要是参考这篇论文的。

参考文档

Zookeeper ZAB 协议分析
ZooKeeper’s atomic broadcast protocol:Theory and practice

Zookeeper ZAB 协议分析[转]的更多相关文章

  1. Zookeeper ZAB 协议分析

    前言 ZAB 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议.在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeep ...

  2. zookeeper ZAB协议 Follower和leader源码分析

    Follower处理逻辑 void followLeader() throws InterruptedException { //... try { //获取leader server QuorumS ...

  3. zookeeper 入门系列-理论基础 – zab 协议

    上一章讨论了paxos算法,把paxos推到一个很高的位置.但是,paxos有没有什么问题呢?实际上,paxos还是有其自身的缺点的: 1. 活锁问题.在base-paxos算法中,不存在leader ...

  4. 分布式协调组件Zookeeper之 选举机制与ZAB协议

    Zookeeper简介: Zookeeper是什么: Zookeeper 是⼀个分布式协调服务的开源框架. 主要⽤来解决分布式集群中应⽤系统的⼀致性问题, 例如怎样避免同时操作同⼀数据造成脏读的问题. ...

  5. ZooKeeper之ZAB协议

    ZooKeeper为高可用的一致性协调框架,自然的ZooKeeper也有着一致性算法的实现,ZooKeeper使用的是ZAB协议作为数据一致性的算法,ZAB(ZooKeeper Atomic Broa ...

  6. zookeeper核心-zab协议-《每日五分钟搞定大数据》

    上篇文章<paxos与一致性>说到zab是在paxos的基础上做了重要的改造,解决了一系列的问题,这一篇我们就来说下这个zab. zab协议的全称是ZooKeeper Atomic Bro ...

  7. zookeeper 负载均衡 核心机制-实现原理 包含ZAB协议(滴滴,阿里面试)

    面试也经常问kafka的原理,以及zookeeper与kafka原理的区别:kafka 数据一致性-leader,follower机制与zookeeper的区别: zookeeper是如何实现负载均衡 ...

  8. Zookeeper一致性协议原理Zab

    ZooKeeper为高可用的一致性协调框架,自然的ZooKeeper也有着一致性算法的实现,ZooKeeper使用的是ZAB协议作为数据一致性的算法, ZAB(ZooKeeper Atomic Bro ...

  9. Zookeeper架构、ZAB协议、选举

    转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制  (nice) ZooKeeper学习第六期---ZooKeeper机制架构 一.Zookee ...

随机推荐

  1. WCF DEMO2 基于HTTP-GET的元数据交换及Configure()方法以及添加MEX终结点

    using System; using System.Diagnostics; using System.Linq; using System.ServiceModel; using System.S ...

  2. vue setTimeout--延迟操作

    有时候我们在查询后要做某些事情,例如我查询的时候要根据某个值再去查询某些东西并和这些值一起显示的时候,我们可以对渲染数据的操作进行延迟,因为代码执行的速度是很快的而访问数据的操作相对于渲染的速度慢得多 ...

  3. EF 多种查询方式

    比较常用的查询方式linq to entity,这里先看一种写法: var query = (from d in testContext.Set<DepartPerson>() //查询和 ...

  4. JVM垃圾回收器之G1(Garbage First)--new

    相比CMS收集器有两个显著的改进: (1). G1收集器是基于“标记-整理”算法实现的收集器,不会产生空间碎片 (2). 它可以精确地控制停顿,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在 ...

  5. css画一个提示框

    用css画一个如下图的提示框: 代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  6. springMVC定时任务总是执行两次

    情况: springmvc的定时任务在本机上测试的时候没有问题,但是放到测试服务器上的时候总是执行两次: 探索:(网上搜索) 一.spring注入的时候实例化了多次,说是spring-servlet. ...

  7. js判断移动端页面按home键切换到桌面事件

    ---恢复内容开始--- 原理就是通过页面标签切换事件(visibilitychange)来判断,亦可用户移动端桌面和app切换. 先看代码: var hiddenProperty = 'hidden ...

  8. LNMP下安装memcache

    转自:LNMP 添加 memcached服务 由于memcached具有更多的功能和服务,已经不推荐使用memcache了.(缺少个字母d) 1. 首先安装memcached服务端. 这里使用yum源 ...

  9. x86项目中读取注册表Register数据项的方法

    x86项目中使用Registry读取key/value的时候,会出现重定向的问题,解决方法如下: public static string GetMachineGuid() { string guid ...

  10. 关于 未在本地计算机上注册“VFPOLEDB.1” 的解决方案

    在很古老的时候猿们会使用 Microsoft Visual FoxPro(即Dbf)的数据库,用于对数据的存储,和Access类似,而且两者可以互转,可以把它当成数据文件,如Access数据(MDB) ...