3.5 Zookeeper实现原理

Zookeeper 服务有两种不同的运行模式.

  • 一种是独立模式(standalone mode)
  • 一种是复制模式(replicated mode)

3.5.1 独立模式

这种模式比较简单, 只有一个 Zookeeper 服务器. 比较适合于测试环境(也可以在单元测试中采用), 但是不能保证高可用和可恢复性.

3.5.2 复制模式

在生产环境中的 Zookeeper 通常以复制模式运行在一个计算机集群上, 这个计算机集群通常被称为一个集合体(ensemble).

Zookeeper 通过复制来实现高可用性, 只要集合体中半数以上(不包括半数)的机器处于可用状态, 它就能够提供服务.##

例如:

在一个有 5 台机器的集合体中, 任意 2 机器出现故障, 都可以保证服务继续, 因为剩下的 3 台机器超过了半数.

在 6 个机器的集合体中, 最多只能容忍 2 台机器出现故障, 因为如果 3 台机器出现故障, 剩下的 3 台就没有超过集合体的半数了.

处于这个原因, 一个集合体中通常包含奇数台机器.


从概念上来说, Zookeeper 是非常简单的: 他所要做的就是确保对 znode 树的每一个修改都会被复制到集合体中的超过半数的机器上.

如果有不到半数的机器出现故障, 则最少会有一台机器保存最新的状态, 其余的副本最终也会更新到这个状态.

然而, 这个简单的想法的实现却不简单. Zookeeper 使用了 Zab 协议, 该协议包括以下两个无限重复的阶段:

阶段1: 领导者选择(Leader election)

集合体中每台机器都有一个身份: 要么是领导者(leader), 要么是跟随者(follower).

一个集合体中只有一个领导者, 其余都是跟随者.

集合体中所有机器通过一个选举过程来选出一台机器来作为领导者, 其他的机器就称为了跟随者.

阶段2: 原子广播(Atomic broadcast)

所有的写请求都会被转发给领导者, 再有领导者将更新广播给跟随者.

当半数以上的跟随者已经将修改持久化之后, 领导者才会真正的提交这个更新, 然后客户端才会收到一个更新成功的响应.

这个用来达成共识的协议被设计成具有原子性, 因此每个修改要么成功要么失败.


如果领导者出现故障, 其余的机器会自动再选出另外一个领导者, 并和新的领导者一起继续提供服务. 随后, 如果之前的领导者恢复正常, 则会成为一个跟随者.

领导者的选举过程是非常快的, 只需要大概200毫秒, 因此在领导者选举的过程中不会出现系统性能的明显降低.


任何一台机器都可以为读请求提供服务, 并且由于读请求只涉及内存检索, 因此非常快.


3.5.3 领导者选举过程详解

Leader 选举是保证分布式数据一致性的关键所在。当 Zookeeper 集群中的一台服务器出现以下两种情况之一时,需要进入 Leader 选举:

  1. 服务器初始化启动。
  2. 服务器运行期间无法和 Leader 保持连接。

选举机制中的一些概念

  • 服务器ID(myid)

    比如有 5 台服务器, 他们的 ID 编号分别是1, 2, 3, 4, 5.

    编号越大, 在选举算法中的权重也越大.
  • 数据ID(或者也叫事务ID, zxid)

    服务器中存放的最大数据ID.

    值越大表示数据越新, 在选举算法中数据越新权重越大.
  • 逻辑时钟

    或者叫投票的次数.
    同一轮投票过程中的逻辑时钟值是相同的。 每投完一次票这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比,根据不同的值做出不同的判断。

  • 选举状态

    • LOOKING : 精选状态(正在找领导)
    • FOLLOWING : 随从状态,同步leader状态,参与投票。
    • OBSERVING : 观察状态, 同步leader状态,不参与投票。
    • LEADING : 领导者状态(我是领导了)
  • 选举消息内容 在投票完成后,需要将投票信息发送给集群中的所有服务器,它包含如下内容。

    • 服务器ID
    • 数据ID
    • 逻辑时钟
    • 选举状态

服务器启动时期的 Leader 选举

目前有 5 台服务器,每台服务器均没有数据(可以认为他们的数据id都是0, 所以选领导看每个服务器的id),它们的编号分别是1,2,3,4,5,按编号依次启动,它们的选择举过程如下:

  1. 服务器1启动, 给自己投票, 然后广播投票信息(<1, 0> 格式: <myid, zxid>). 由于其他服务器都没有启动, 所以收不到任何反馈信息.服务器1的状态一直属于LOOKING

  2. 服务器2启动, 给自己投票, 然后广播投票信息(<2, 0>)(与其他服务器交换选举信息).由于服务器的2的id大于服务器1的id, 所以服务器2胜出. 由于现在启动的服务器的没有超过半数, 所以服务器2并不能当成为leader, 仍然是LOOKING状态. 但是服务器1会更新的自己的投票信息为(<2, 0>).

  3. 服务器3启动, 给自己投票(<3, 0>), 与其他服务器交换投票信息. 最终的结果是服务器3胜出, 且由于启动的服务器的数量已经超过了半数, 所以服务器3成为leader, 服务器1和服务器2自动成为follower

  4. 服务器4启动, 根据前面的信息, 虽然服务器4的id比较大, 但是由于已经产生了领导, 所以服务器4只能是follower

  5. 服务器5启动, 命运和服务器4一样.

服务器运行时期的 Leader 选择( Leader 挂了)

在 Zookeeper 运行期间,Leader 与 非Leader 服务器各司其职,即便当有非Leader服务器宕机或新加入,此时也不会影响Leader.

但是一旦Leader服务器挂了,那么整个集群将暂停对外服务(200ms左右),进入新一轮Leader选举,其过程和启动时期的Leader选举过程基本一致。

假设正在运行的有Server1Server2Server3Server4Server5三台服务器,当前LeaderServer3,若某一时刻Leader挂了,此时便开始Leader选举。选举过程如下:

为了分析方便, 假设仍然没有数据.(如果有数据的话, 数据id优先.)

  1. 变更状态. 所有的follower都会讲自己的服务器状态变成LOOKING.

  2. 开始选举, 每个服务器发送一个投票. 第一轮投票都会选举自己.<自己的id, 0>

  3. 每个服务器都会接收到其他服务器的投票. 与气动过程相同

  4. 处理投票

  5. 统计投票

  6. 选出领导, 更新状态.

Copyright © 尚硅谷大数据 & 2019 all right reserved,powered by Gitbook
该文件最后修订时间: 2018-10-18 11:15:50

results matching ""

    No results matching ""