乐趣区

关于java:zookeeper核心之ZAB协议就这么简单

背景

咱们都晓得 Zookeeper 是基于 ZAB 协定实现的,在介绍 ZAB 协定之前,先回顾一下 Zookeeper 的起源与倒退。

Zookeeper 到底是在什么样的时代背景下被提出?为了解决了哪些辣手的问题?

Zookeeper 最早起源于雅虎研究院的一个钻研小组。过后,钻研人员发现,在雅虎的很多大型零碎根本都须要依赖一个相似的零碎来进行分布式协调,然而这些零碎都存在分布式单点问题,所以雅虎的开发人员就试图开发出一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在解决业务逻辑上。

于是,Zookeeper 就诞生了!

Zookeeper 的呈现不仅解决了分布式系统下数据一致性的问题,而且经验过线上验证,无论是从性能、易用性、稳定性上来说,都是工业级产品的规范。能够说在分布式系统中具备不可代替的外围位置,Hadoop、HBase、Storm 和 Solr 等大型分布式系统都曾经将 Zookeeper 作为其外围组件,用于分布式协调。即使 Zookeeper 如此优良,然而 Zookeeper 仍然是收费且开源的,全世界成千上万的开发者都关注着它,陪同着一起成长和倒退。

作为一个开发者无论是为了应酬面试、降职还是集体技术成长的须要,都须要对 Zookeeper 有所理解,而学习 Zookeeper 的要害就是了解其外围局部:

ZAB 协定,全称(Zookeeper Atomic Broadcast)Zookeeper 原子音讯播送协定。

它与 Paxos 相似,也是一种数据一致性的算法。

Zookeeper 应该具备的个性

在 ZAB 协定的开发设计人员在协定设计之初并没有要求 ZAB 具备很好的扩展性,最后只是为了雅虎公司外部哪些高吞吐量、低提早、强壮、简略的分布式系统场景设计的。基于 ZAB 协定,Zookeeper 实现了一种主备模式的零碎架构来放弃集群中各正本之间数据的一致性,简略架构图如下:

Zookeeper 用一个繁多的主过程来接管并解决客户端的所有事物申请,并采纳 ZAB 的原子播送协定将服务器数据状态以事物 Proposal 的模式播送到所有的正本过程中去。这样的模式就保障了,在同一时刻只有一个主过程来播送服务器的状态更变,因而可能很好地解决客户端大量的并发申请,这在 ZAB 协定中叫:音讯播送。

除此之外,在分布式环境中事物的执行程序也会存在肯定的先后关系,比方:事务 C 的写入须要依赖事务 B 的写入,而事务 B 写入须要依赖事务 A 写入。这种前后依赖的程序也对 ZAB 协定提出了一个要求:ZAB 协定须要保障如果一个状态的变更被解决了,那么所有其依赖的状态变更都曾经被提前解决了。也就是须要程序执行。

另外除了能失常播送音讯、音讯的程序执行,主过程也可能随时会因为断电、机器宕机等异常情况无奈提供服务,因而,ZAB 协定还须要做到在以后主过程呈现上述异常情况的时候仍然可能失常工作,这在 ZAB 协定中叫:解体复原。

所以整个 ZAB 协定须要具备的外围个性曾经被形容进去了,处理事务的申请的形式能够简略了解为:

所有的事务申请必须由一个全局惟一的服务器来协调解决,这样的服务器叫:Leader 服务器。其余的服务器被称为 Follower 服务器。Leader 服务器将客户端事务申请转化成一个事务 Prososal(提议),并将改 Proposal 分发给集群中所有的 Follower 服务器。之后 Leader 服务器接管了正确的反馈后,那么 Leader 就会再次向所有的 Follower 服务器散发 Commit 音讯,要求将前一个 Proposal 提交。

这就简略论述了ZAB 协定中音讯播送模式的局部内容

ZAB 协定的两种模式

ZAB 协定的包含两种模式:解体复原 音讯播送

既然有两种模式,那 Zookeeper 集群什么时候进入奔溃恢复模式?什么时候进入音讯播送模式呢?

在进入 奔溃复原 模式时 Zookeeper 集群会进行 Leader 选举,个别有两种状况会产生选举:

  • 当服务器启动期间会进行 Leader 选举。
  • 当服务器运行期 Leader 服务器的呈现网络中断、奔败退出、重启等异常情况,或者当集群中半数的服务器与该 Leader 服务器无奈通信时,进入解体恢复模式,开始 Leader 选举。

选举出 Leader 服务器后,会进入 音讯播送模式,开始接管解决客户端的申请,前文曾经形容,这里不再赘述。

相干名词概念

在深刻解说 ZAB 协定的两个模式之前,先解释 Zookeeper 的几个相干概念,不便了解 ZAB 协定:

三种角色

在后面提到 Zookeeper 的集群中的服务器有 Leader 和 Follower,但理论在 ZAB 协定中 Zookeeper 有三种角色,别离是 Leader、Folower、Observer,它们的分工各有不同:

  • Leader:负责整个 Zookeeper 集群工作机制中的外围,次要工作有一下两个:

    • 事务申请的惟一调度和解决者,保障集群事务处理的程序性
    • 集群外部各服务器的调度者
  • Follower:它是 Leader 的追随者,其次要工作有三个:

    • 解决客户端的非实物申请,转发事务申请给 Leader 服务器
    • 参加事务申请 Proposal 的投票
    • 参加 Leader 选举投票
  • Observer:是 zookeeper 自 3.3.0 开始引入的一个角色,它不参加事务申请 Proposal 的投票,也不参加 Leader 选举投票,只提供非事务的服务(查问),通常在不影响集群事务处理能力的前提下晋升集群的非事务处理能力。
三种状态

在晓得了 Zookeeper 中有三种角色后,不经发问:Zookeeper 是如何晓得本人目前是什么角色的呢?

在 ZAB 协定中定义:通过本身的状态来辨别本人的角色的,在运行期间各个过程可能呈现以下三种状态之一:

  • LOOKING:处在这个状态时,会进入 Leader 选举状态
  • FOLLOWER:Follower 服务器和 Leader 服务器放弃同步时的状态
  • LEADING:Leader 服务器作为主过程领导者的状态

在组成 ZAB 协定的所有过程启动的时候,初始化状态都是 LOOKING 状态,此时过程组中不存在 Leader,选举之后才有,在进行选举胜利后,就进入音讯播送模式,此时 Zookeeper 集群中的角色状态就不再是 LOOKING 状态。

ZXID

前文咱们晓得 zookeeper 音讯有严格的因果关系,因而必须将每一个事务申请依照先后顺序来进行排序与解决。那 Zookeeper 是如何放弃申请解决的程序的呢?其中十分要害的点就是 ZXID。

那 ZXID 到底是怎么发挥作用的呢?

Leader 服务器在接管到事务申请后,会为每个事务申请生成对应的 Proposal 来进行播送,并且在播送事务 Proposal 之前,Leader 服务器会首先为这个事务 Proposal 调配一个全局枯燥递增的惟一 ID,咱们称之为事务 ID(即 ZXID)。

ZXID 的设计也很有特点,是一个全局有序的 64 位的数字,能够分为两个局部:

  • 高 32 位是:epoch(纪元),代表着周期,每当选举产生一个新的 Leader 服务器时就会取出其本地日志中最大事务的 ZXID,解析出 epoch(纪元)值操作加 1 作为新的 epoch,并将低 32 地位零。
  • 低 32 位是:counter(计数器),它是一个简略的枯燥递增的计数器,针对客户端的每个事务申请都会进行加 1 操作;

这里低 32 位 counter(计数器)枯燥递增还好了解,高 32 位 epoch(纪元)每次选举加 1 兴许有些同学就有疑难了,为什么 epoch(纪元)每次选须要举加 1,它在整个 ZAB 协定中有什么作用?

咱们晓得每当选举产生一个新的 Leader 服务器时生成一个新的 epoch(纪元)值,而在前文咱们晓得,服务运行过程中触发选举 Leader 的条件是:Leader 服务器的呈现网络中断、奔败退出、重启等异常情况,或者当集群中半数的服务器与该 Leader 服务器无奈通信时

这阐明整个 Zookeeper 集群此时处于一个异样的状况下,而在产生异样前,音讯播送进行到哪一步骤咱们基本不晓得,集群中的其余 Follower 节点从这种解体复原状态从新选举出 Leader 后,如果老 Leader 又复原了连贯进入集群。此时老 Leader 的 epoch 必定会小于新 Leader 的 epoch,这时就将老 Leader 变成 Follower,对新的 Leader 进行数据同步。即使这时老 Leader 对其余的 Follower 节点发送了申请,Follower 节点也会比拟 ZXID 的值,因为高 32 位加 1 了,Follower 的 epoch(纪元)大于老 Leader 的 epoch(纪元),所以 Follower 会疏忽这个申请。

这像改朝换代一样,前朝的剑不能斩本朝的官。

音讯播送模式

晓得了这些名词,和上文提到的零散的知识点,其实解体恢复模式和音讯播送模式的过程大家大抵有所理解了。

先看看音讯播送模式吧!

音讯播送的模式的过程简图如下所示:

整个过程相似一个二阶段提交的过程,但却有所不同,ZAB 协定简化了二阶段提交模型,在超过半数的 Follower 服务器曾经反馈 ACK 之后就开始提交事务 Prososal 了,无需期待所有服务器响应。

联合上图,看看音讯播送的具体细节:

  • Leader 服务器接管到申请后在进行播送事务 Proposal 之前会为这个事务调配一个 ZXID,再进行播送。
  • Leader 服务器会为每个 Follower 服务器都各自调配一个独自的队列,而后将须要播送的事务 Proposal 顺次放入这些队列中去,并依据 FIFO 策略进行音讯的发送。
  • 每个 Follower 服务器在接管到后都会将其以事务日志的模式写入到本地磁盘中,并且在胜利写入后返回 Leader 服务器一个 ACK 响应。
  • 当有超过半数的服务器 ACK 响应后,Leader 就会播送一个 Commit 音讯给所有的 Follower 服务器,Follower 接管到后就实现对事务的提交操作。

在画一张具体点的流程图,更直观:

这就实现了整个音讯播送了!

解体恢复模式

前文曾经重复提过解体恢复模式了,其实就是从新选举出新的 Leader 服务器,选举实现后 Follower 服务器在再去同步 Leader 的数据。

运行中的服务再次进行从新选举,肯定是呈现某种异样,咱们晓得在出现异常状况之前 Leader 的音讯播送可能会处在任何一个阶段,有可能客户端的申请只是在 Leader 服务器上提出并未被提交,也可能申请曾经被 Leader 服务器提交。

ZAB 协定对于不同阶段的呈现的数据不统一的状况做了兼容,保障:

  • 曾经在 Leader 服务器上 提交 的事务,最终会被所有服务器都提交
  • 只在 Leader 服务器上 提出 的事务,要抛弃

针对以上的两个要求,在进行 Leader 选举时,之须要选举出集群中 ZXID 最大的事务 Proposal 即可,这样就能够省去 Leader 服务器查看 Proposal 的提交和抛弃工作了。因为 Leader 服务器的事务是最大的,所有以 Leader 服务器的数据为规范即可。

ZXID 在集群中其实并不是惟一的,所以也有可能呈现多 Follower 服务器 ZXID 雷同的状况,这时候就须要比拟 Zookeeper 的 SID 值。什么是 SID?SID 是一个数字,和 zookeeper 的 myid 统一,myid 就不要解释了,装置过 Zookeeper 的都晓得,每台服务器都须要配置一个这样的文件,外面只有一个数字,用来标识这台服务器。因为每台机器的 myid 配置都不一样,所以集群选举的时不会呈现相等的状况。

选举时,比拟大小的源码如下:

后面曾经说过,呈现选举 Leader 可能会呈现两种状况:

  • 服务启动期间,发动选举
  • 服务运行期间,出现异常,发动选举

但无论是启动期还是运行期进行 Leader 选举,其选举过程都差不太多,我简略画个流程图:

联合上图,奔溃恢复模式下 Leader 选举的过程细节如下:

  • 检测节点处于 LOOKING 阶段,开发选举 Leader
  • 发动投票时有两种状况:

    • 在服务启动的初始阶段,每个服务器都会投票给本人以(myid,zxid)的信息模式发送,那初始阶段没有 zxid 值,就会发送(myid,0)
    • 在服务器运行期间,每个服务器上的 zxid 都有值,且 zxid 都不雷同,所以就失常发送(myid,zxid)
  • 各节点收到信息后将收到的(myid,zxid)和本人的比拟,比拟的过程后面曾经说过,这里不再赘述
  • 而后判断是否有半数的机器投票选出 Leader,如果否,在进入新一轮投票,直到选出
  • 选出 Leader 后,其余节点就变成 Follower 角色,并向 Leader 发送本人服务器的最大 zxid,Leader 服务器收到后会和本人本地的提议缓存队列进行比拟,判断应用那种策略进行同步(前面具体阐明同步的四种策略)
  • 当同步实现,集群就能够失常的解决申请了,就进入音讯播送模式了。

这就是解体恢复模式下选举 Leader 的过程了!

上面再简略介绍下数据同步的四种策略,这四种同步策略保障了 Zookeeper 集群中的数据一致性,也解决了前文提出的两个问题,兼容了各种数据不统一的场景。

数据同步的四种策略

在数据同步之前,Leader 服务器会进行数据同步的初始化,首先会从 Zookeeper 的内存数据库中提取出事务后期对应的提议缓存队列,同时会初始化三个 ZXID 的值:

  • peerLastZxid:这是 Follower 的最初解决 ZXID
  • minCommittedLog:Leader 服务器的提议缓存队列中 最小的 ZXID
  • maxCommittedLog:Leader 服务器的提议缓存队列中 最大的 ZXID

依据这三个参数,就能够确定四种同步形式,别离为:

  • 间接差异化同步

    • 场景:当 minCommittedLog < peerLastZxid < maxCommittedLog 时
  • 先回滚在差异化同步

    • 场景:如果集群有 A、B、C 三台机器,此时 A 是 Leader 然而 A 挂了,在挂之前 A 生成了一个提议假如是:03,而后集群有从新选举 B 为新的 Leader,此时生成的的提议缓存队列为:01~02,B 和 C 进行同步之后,生成新的纪元,ZXID 从 10 开始计数,集群进入播送模式解决了局部申请,假如当初 ZXID 执行到 15 这个值,此时 A 复原了退出集群,这时候就比拟 A 最初提交的 ZXID:peerLastZxid 与 minCommittedLog、maxCommittedLog 的关系。此时尽管合乎间接差异化同步:minCommittedLog < peerLastZxid < maxCommittedLog 这样的关系,然而提议缓存队列中却没有这个 ZXID,这时候就须要先回滚,在进行同步。
  • 仅回滚同步

    • 场景:这里和先回滚在差异化同步相似,间接回滚就能够。
  • 全量同步

    • 场景:peerLastZxid < minCommittedLog,当远远落后 Leader 的数据时,间接全量同步。

这就是四种同步策略,这几种同步形式也解决了上文提出的问题:

  • 只在 Leader 服务器上提出的事务,要抛弃(这个问题会在同步时,会进行回滚,使得只在 Leader 服务器上提出的事务抛弃)

这些就是整个 ZAB 协定中解体复原的内容。

ZAB 协定和 Paxos 算法的区别

ZAB 协定看起来和 Paxos 有着相同之处,但它并不是 Paxos 的典型实现,其实还是有一些区别,ZAB 协定中额定增加了一个同步的阶段,两者设计指标也不太一样,ZAB 协定次要用于构建一个高可用的分布式数据主备零碎,而 Paxos 算法则是用于构建一个分布式一致性的状态机。

总结

Zookeeper 作为杰出的分布式协调服务,目前读 QPS 达到 12w,杰出的性能也让开发者更加青眼,其 ZAB 协定的外围分为两个局部:解体复原、音讯播送。

典型的利用场景有:

  • 数据公布 / 订阅、负载平衡
  • 命名服务
  • 分布式协调告诉
  • 集群治理
  • Master 选举
  • 分布式锁
  • 分布式队列
  • 用 Zookeeper 防止脑裂

除此之外在大数据畛域也有利用,例如:

  • Hadoop
  • HBase
  • Kafka

在阿里巴巴团体外部实际的 Zookeeper 的产品也有很多,如:

  • 消息中间件:Metamorphosis
  • RPC 服务框架:Dubbo
  • 基于 MySQL Binlog 的增量订阅和生产组件:Cancel
  • 分布式数据库同步零碎:Otter
  • 实时计算引擎:JStorm

zookeeper 外围 –ZAB 协定

背景

咱们都晓得 Zookeeper 是基于 ZAB 协定实现的,在介绍 ZAB 协定之前,先回顾一下 Zookeeper 的起源与倒退。
Zookeeper 到底是在什么样的时代背景下被提出?为了解决了哪些辣手的问题?
Zookeeper 最早起源于雅虎研究院的一个钻研小组。过后,钻研人员发现,在雅虎的很多大型零碎根本都须要依赖一个相似的零碎来进行分布式协调,然而这些零碎都存在分布式单点问题,所以雅虎的开发人员就试图开发出一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在解决业务逻辑上。
于是,Zookeeper 就诞生了!
Zookeeper 的呈现不仅解决了分布式系统下数据一致性的问题,而且经验过线上验证,无论是从性能、易用性、稳定性上来说,都是工业级产品的规范。能够说在分布式系统中具备不可代替的外围位置,Hadoop、HBase、Storm 和 Solr 等大型分布式系统都曾经将 Zookeeper 作为其外围组件,用于分布式协调。即使 Zookeeper 如此优良,然而 Zookeeper 仍然是收费且开源的,全世界成千上万的开发者都关注着它,陪同着一起成长和倒退。
作为一个开发者无论是为了应酬面试、降职还是集体技术成长的须要,都须要对 Zookeeper 有所理解,而学习 Zookeeper 的要害就是了解其外围局部:
ZAB 协定,全称(Zookeeper Atomic Broadcast)Zookeeper 原子音讯播送协定。
它与 Paxos 相似,也是一种数据一致性的算法。

Zookeeper 应该具备的个性

在 ZAB 协定的开发设计人员在协定设计之初并没有要求 ZAB 具备很好的扩展性,最后只是为了雅虎公司外部哪些高吞吐量、低提早、强壮、简略的分布式系统场景设计的。基于 ZAB 协定,Zookeeper 实现了一种主备模式的零碎架构来放弃集群中各正本之间数据的一致性,简略架构图如下:
Zookeeper 用一个繁多的主过程来接管并解决客户端的所有事物申请,并采纳 ZAB 的原子播送协定将服务器数据状态以事物 Proposal 的模式播送到所有的正本过程中去。这样的模式就保障了,在同一时刻只有一个主过程来播送服务器的状态更变,因而可能很好地解决客户端大量的并发申请,这在 ZAB 协定中叫:音讯播送。
除此之外,在分布式环境中事物的执行程序也会存在肯定的先后关系,比方:事务 C 的写入须要依赖事务 B 的写入,而事务 B 写入须要依赖事务 A 写入。这种前后依赖的程序也对 ZAB 协定提出了一个要求:ZAB 协定须要保障如果一个状态的变更被解决了,那么所有其依赖的状态变更都曾经被提前解决了。也就是须要程序执行。
另外除了能失常播送音讯、音讯的程序执行,主过程也可能随时会因为断电、机器宕机等异常情况无奈提供服务,因而,ZAB 协定还须要做到在以后主过程呈现上述异常情况的时候仍然可能失常工作,这在 ZAB 协定中叫:解体复原。
所以整个 ZAB 协定须要具备的外围个性曾经被形容进去了,处理事务的申请的形式能够简略了解为:

所有的事务申请必须由一个全局惟一的服务器来协调解决,这样的服务器叫:Leader 服务器。其余的服务器被称为 Follower 服务器。Leader 服务器将客户端事务申请转化成一个事务 Prososal(提议),并将改 Proposal 分发给集群中所有的 Follower 服务器。之后 Leader 服务器接管了正确的反馈后,那么 Leader 就会再次向所有的 Follower 服务器散发 Commit 音讯,要求将前一个 Proposal 提交。
这就简略论述了ZAB 协定中音讯播送模式的局部内容

ZAB 协定的两种模式

ZAB 协定的包含两种模式:解体复原 音讯播送
既然有两种模式,那 Zookeeper 集群什么时候进入奔溃恢复模式?什么时候进入音讯播送模式呢?
在进入 奔溃复原 模式时 Zookeeper 集群会进行 Leader 选举,个别有两种状况会产生选举:

  • 当服务器启动期间会进行 Leader 选举。
  • 当服务器运行期 Leader 服务器的呈现网络中断、奔败退出、重启等异常情况,或者当集群中半数的服务器与该 Leader 服务器无奈通信时,进入解体恢复模式,开始 Leader 选举。

选举出 Leader 服务器后,会进入 音讯播送模式,开始接管解决客户端的申请,前文曾经形容,这里不再赘述。

相干名词概念

在深刻解说 ZAB 协定的两个模式之前,先解释 Zookeeper 的几个相干概念,不便了解 ZAB 协定:

三种角色

在后面提到 Zookeeper 的集群中的服务器有 Leader 和 Follower,但理论在 ZAB 协定中 Zookeeper 有三种角色,别离是 Leader、Folower、Observer,它们的分工各有不同:

  • Leader:负责整个 Zookeeper 集群工作机制中的外围,次要工作有一下两个:

    • 事务申请的惟一调度和解决者,保障集群事务处理的程序性
    • 集群外部各服务器的调度者
  • Follower:它是 Leader 的追随者,其次要工作有三个:

    • 解决客户端的非实物申请,转发事务申请给 Leader 服务器
    • 参加事务申请 Proposal 的投票
    • 参加 Leader 选举投票
  • Observer:是 zookeeper 自 3.3.0 开始引入的一个角色,它不参加事务申请 Proposal 的投票,也不参加 Leader 选举投票,只提供非事务的服务(查问),通常在不影响集群事务处理能力的前提下晋升集群的非事务处理能力。
三种状态

在晓得了 Zookeeper 中有三种角色后,不经发问:Zookeeper 是如何晓得本人目前是什么角色的呢?
在 ZAB 协定中定义:通过本身的状态来辨别本人的角色的,在运行期间各个过程可能呈现以下三种状态之一:

  • LOOKING:处在这个状态时,会进入 Leader 选举状态
  • FOLLOWER:Follower 服务器和 Leader 服务器放弃同步时的状态
  • LEADING:Leader 服务器作为主过程领导者的状态

在组成 ZAB 协定的所有过程启动的时候,初始化状态都是 LOOKING 状态,此时过程组中不存在 Leader,选举之后才有,在进行选举胜利后,就进入音讯播送模式,此时 Zookeeper 集群中的角色状态就不再是 LOOKING 状态。

ZXID

前文咱们晓得 zookeeper 音讯有严格的因果关系,因而必须将每一个事务申请依照先后顺序来进行排序与解决。那 Zookeeper 是如何放弃申请解决的程序的呢?其中十分要害的点就是 ZXID。
那 ZXID 到底是怎么发挥作用的呢?
Leader 服务器在接管到事务申请后,会为每个事务申请生成对应的 Proposal 来进行播送,并且在播送事务 Proposal 之前,Leader 服务器会首先为这个事务 Proposal 调配一个全局枯燥递增的惟一 ID,咱们称之为事务 ID(即 ZXID)。
ZXID 的设计也很有特点,是一个全局有序的 64 位的数字,能够分为两个局部:

  • 高 32 位是:epoch(纪元),代表着周期,每当选举产生一个新的 Leader 服务器时就会取出其本地日志中最大事务的 ZXID,解析出 epoch(纪元)值操作加 1 作为新的 epoch,并将低 32 地位零。
  • 低 32 位是:counter(计数器),它是一个简略的枯燥递增的计数器,针对客户端的每个事务申请都会进行加 1 操作;

这里低 32 位 counter(计数器)枯燥递增还好了解,高 32 位 epoch(纪元)每次选举加 1 兴许有些同学就有疑难了,为什么 epoch(纪元)每次选须要举加 1,它在整个 ZAB 协定中有什么作用?
咱们晓得每当选举产生一个新的 Leader 服务器时生成一个新的 epoch(纪元)值,而在前文咱们晓得,服务运行过程中触发选举 Leader 的条件是:Leader 服务器的呈现网络中断、奔败退出、重启等异常情况,或者当集群中半数的服务器与该 Leader 服务器无奈通信时
这阐明整个 Zookeeper 集群此时处于一个异样的状况下,而在产生异样前,音讯播送进行到哪一步骤咱们基本不晓得,集群中的其余 Follower 节点从这种解体复原状态从新选举出 Leader 后,如果老 Leader 又复原了连贯进入集群。此时老 Leader 的 epoch 必定会小于新 Leader 的 epoch,这时就将老 Leader 变成 Follower,对新的 Leader 进行数据同步。即使这时老 Leader 对其余的 Follower 节点发送了申请,Follower 节点也会比拟 ZXID 的值,因为高 32 位加 1 了,Follower 的 epoch(纪元)大于老 Leader 的 epoch(纪元),所以 Follower 会疏忽这个申请。
这像改朝换代一样,前朝的剑不能斩本朝的官。

音讯播送模式

晓得了这些名词,和上文提到的零散的知识点,其实解体恢复模式和音讯播送模式的过程大家大抵有所理解了。
先看看音讯播送模式吧!
音讯播送的模式的过程简图如下所示:
<img src=”https://upload-images.jianshu.io/upload_images/2710833-927c4264c545c4e7.png” alt=”image.png” />
整个过程相似一个二阶段提交的过程,但却有所不同,ZAB 协定简化了二阶段提交模型,在超过半数的 Follower 服务器曾经反馈 ACK 之后就开始提交事务 Prososal 了,无需期待所有服务器响应。
联合上图,看看音讯播送的具体细节:

  • Leader 服务器接管到申请后在进行播送事务 Proposal 之前会为这个事务调配一个 ZXID,再进行播送。
  • Leader 服务器会为每个 Follower 服务器都各自调配一个独自的队列,而后将须要播送的事务 Proposal 顺次放入这些队列中去,并依据 FIFO 策略进行音讯的发送。
  • 每个 Follower 服务器在接管到后都会将其以事务日志的模式写入到本地磁盘中,并且在胜利写入后返回 Leader 服务器一个 ACK 响应。
  • 当有超过半数的服务器 ACK 响应后,Leader 就会播送一个 Commit 音讯给所有的 Follower 服务器,Follower 接管到后就实现对事务的提交操作。

在画一张具体点的流程图,更直观:
<img src=”https://upload-images.jianshu.io/upload_images/2710833-e53b8b881792203a.png” alt=”image.png” />
这就实现了整个音讯播送了!

解体恢复模式

前文曾经重复提过解体恢复模式了,其实就是从新选举出新的 Leader 服务器,选举实现后 Follower 服务器在再去同步 Leader 的数据。
运行中的服务再次进行从新选举,肯定是呈现某种异样,咱们晓得在出现异常状况之前 Leader 的音讯播送可能会处在任何一个阶段,有可能客户端的申请只是在 Leader 服务器上提出并未被提交,也可能申请曾经被 Leader 服务器提交。
ZAB 协定对于不同阶段的呈现的数据不统一的状况做了兼容,保障:

  • 曾经在 Leader 服务器上 提交 的事务,最终会被所有服务器都提交
  • 只在 Leader 服务器上 提出 的事务,要抛弃

针对以上的两个要求,在进行 Leader 选举时,之须要选举出集群中 ZXID 最大的事务 Proposal 即可,这样就能够省去 Leader 服务器查看 Proposal 的提交和抛弃工作了。因为 Leader 服务器的事务是最大的,所有以 Leader 服务器的数据为规范即可。
ZXID 在集群中其实并不是惟一的,所以也有可能呈现多 Follower 服务器 ZXID 雷同的状况,这时候就须要比拟 Zookeeper 的 SID 值。什么是 SID?SID 是一个数字,和 zookeeper 的 myid 统一,myid 就不要解释了,装置过 Zookeeper 的都晓得,每台服务器都须要配置一个这样的文件,外面只有一个数字,用来标识这台服务器。因为每台机器的 myid 配置都不一样,所以集群选举的时不会呈现相等的状况。
选举时,比拟大小的源码如下:
<img src=”https://upload-images.jianshu.io/upload_images/2710833-bbcba5240c2a1db0.png” alt=”image.png” />
后面曾经说过,呈现选举 Leader 可能会呈现两种状况:

  • 服务启动期间,发动选举
  • 服务运行期间,出现异常,发动选举

但无论是启动期还是运行期进行 Leader 选举,其选举过程都差不太多,我简略画个流程图:
<img src=”https://upload-images.jianshu.io/upload_images/2710833-d87f4a39511a8630.png” alt=”image.png” />
联合上图,奔溃恢复模式下 Leader 选举的过程细节如下:

  • 检测节点处于 LOOKING 阶段,开发选举 Leader
  • 发动投票时有两种状况:

    • 在服务启动的初始阶段,每个服务器都会投票给本人以(myid,zxid)的信息模式发送,那初始阶段没有 zxid 值,就会发送(myid,0)
    • 在服务器运行期间,每个服务器上的 zxid 都有值,且 zxid 都不雷同,所以就失常发送(myid,zxid)
  • 各节点收到信息后将收到的(myid,zxid)和本人的比拟,比拟的过程后面曾经说过,这里不再赘述
  • 而后判断是否有半数的机器投票选出 Leader,如果否,在进入新一轮投票,直到选出
  • 选出 Leader 后,其余节点就变成 Follower 角色,并向 Leader 发送本人服务器的最大 zxid,Leader 服务器收到后会和本人本地的提议缓存队列进行比拟,判断应用那种策略进行同步(前面具体阐明同步的四种策略)
  • 当同步实现,集群就能够失常的解决申请了,就进入音讯播送模式了。

这就是解体恢复模式下选举 Leader 的过程了!
上面再简略介绍下数据同步的四种策略,这四种同步策略保障了 Zookeeper 集群中的数据一致性,也解决了前文提出的两个问题,兼容了各种数据不统一的场景。

数据同步的四种策略

在数据同步之前,Leader 服务器会进行数据同步的初始化,首先会从 Zookeeper 的内存数据库中提取出事务后期对应的提议缓存队列,同时会初始化三个 ZXID 的值:

  • peerLastZxid:这是 Follower 的最初解决 ZXID
  • minCommittedLog:Leader 服务器的提议缓存队列中 最小的 ZXID
  • maxCommittedLog:Leader 服务器的提议缓存队列中 最大的 ZXID

依据这三个参数,就能够确定四种同步形式,别离为:

  • 间接差异化同步

    • 场景:当 minCommittedLog < peerLastZxid < maxCommittedLog 时
  • 先回滚在差异化同步

    • 场景:如果集群有 A、B、C 三台机器,此时 A 是 Leader 然而 A 挂了,在挂之前 A 生成了一个提议假如是:03,而后集群有从新选举 B 为新的 Leader,此时生成的的提议缓存队列为:01~02,B 和 C 进行同步之后,生成新的纪元,ZXID 从 10 开始计数,集群进入播送模式解决了局部申请,假如当初 ZXID 执行到 15 这个值,此时 A 复原了退出集群,这时候就比拟 A 最初提交的 ZXID:peerLastZxid 与 minCommittedLog、maxCommittedLog 的关系。此时尽管合乎间接差异化同步:minCommittedLog < peerLastZxid < maxCommittedLog 这样的关系,然而提议缓存队列中却没有这个 ZXID,这时候就须要先回滚,在进行同步。
  • 仅回滚同步

    • 场景:这里和先回滚在差异化同步相似,间接回滚就能够。
  • 全量同步

    • 场景:peerLastZxid < minCommittedLog,当远远落后 Leader 的数据时,间接全量同步。

这就是四种同步策略,这几种同步形式也解决了上文提出的问题:

  • 只在 Leader 服务器上提出的事务,要抛弃(这个问题会在同步时,会进行回滚,使得只在 Leader 服务器上提出的事务抛弃)

这些就是整个 ZAB 协定中解体复原的内容。

ZAB 协定和 Paxos 算法的区别

ZAB 协定看起来和 Paxos 有着相同之处,但它并不是 Paxos 的典型实现,其实还是有一些区别,ZAB 协定中额定增加了一个同步的阶段,两者设计指标也不太一样,ZAB 协定次要用于构建一个高可用的分布式数据主备零碎,而 Paxos 算法则是用于构建一个分布式一致性的状态机。

总结

Zookeeper 作为杰出的分布式协调服务,目前读 QPS 达到 12w,杰出的性能也让开发者更加青眼,其 ZAB 协定的外围分为两个局部:解体复原、音讯播送。
典型的利用场景有:

  • 数据公布 / 订阅、负载平衡
  • 命名服务
  • 分布式协调告诉
  • 集群治理
  • Master 选举
  • 分布式锁
  • 分布式队列
  • 用 Zookeeper 防止脑裂

除此之外在大数据畛域也有利用,例如:

  • Hadoop
  • HBase
  • Kafka

在阿里巴巴团体外部实际的 Zookeeper 的产品也有很多,如:

  • 消息中间件:Metamorphosis
  • RPC 服务框架:Dubbo
  • 基于 MySQL Binlog 的增量订阅和生产组件:Cancel
  • 分布式数据库同步零碎:Otter
  • 实时计算引擎:JStorm

欢送关注我的集体微信公众号:java 之旅

退出移动版