乐趣区

关于zookeeper:面试官问ZooKeeper是强一致的吗怎么实现的

Zookeeper 通过 ZAB 保障分布式事务的最终一致性。

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

1.ZAB 是一种专门为 Zookeeper 设计的一种反对 解体复原 的 原子播送协定,是 Zookeeper 保证数据一致性的外围算法。ZAB 借鉴了 Paxos 算法,但它不是通用的一致性算法,是特地为 Zookeeper 设计的。

2. 基于 ZAB 协定,Zookeeper 实现了⼀种主备模式的零碎架构来放弃集群中各正本之间的数据的⼀致性,表现形式就是使⽤⼀个单⼀的主过程(Leader 服务器)来接管并解决客户端的所有事务申请(写申请),并采⽤ ZAB 的原⼦⼴播协定,将服务器数据的状态变更为事务 Proposal 的模式⼴播到所有的 Follower 过程中。

问题提出

  • 主从架构下,leader 解体,数据一致性怎么保障?
  • 选举 leader 的时候,整个集群无奈解决写申请的,如何疾速进行 leader 选举?

ZAB 过程

ZAB 协定的核⼼是 定义了对于那些会扭转 Zookeeper 服务器数据状态的事务申请的解决⽅式

所有事务必须由一个 全局惟一的服务器来协调解决,这样的服务器被称为 Leader 服务器,余下的服务器则称为 Follower 服务器

1.Leader 服务器负责将一个客户端事务申请转化为一个事务 Proposal(提案),并将该 Proposal 分发给集群中所有的 Follower 服务器

2.Leader 服务器期待所有 Follower 服务器的反馈,一旦超过半数的 Follower 服务器进行了正确的反馈后,Leader 就会向所有的 Follower 服务器发送 Commit 音讯,要求将前一个 Proposal 进行提交。

ZAB 协定内容简介

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

音讯播送

当集群中有过半的 Follower 服务器实现了和 Leader 服务器的状态同步,那么整个服务框架就能够进入 音讯播送模式。

当一台恪守 ZAB 协定的服务器启动后退出到集群中,如果此时集群中曾经存在一个 Leader 服务器在负责进行音讯播送,那么退出的服务器会盲目的进入 数据恢复模式:找到 Leader 所在的服务器,并与其进⾏数据同步,数据同步实现后参加到音讯⼴播流程中。

ZAB 协定的音讯播送应用原子播送协定,相似一个二阶段提交的过程,但又有所不同。

1. 二阶段提交中,须要所有参与者反馈 ACK 后再发送 Commit 申请。要求所有参与者要么胜利,要么失败。这样会产生重大的阻塞问题;

2.ZAB 协定中,Leader 期待半数以上的 Follower 胜利反馈 ACK 即可,不须要收到全副的 Follower 反馈 ACK。

音讯播送过程:

1. 客户端发动写申请

2.Leader 将客户端申请信息转化为事务 Proposal,同时为每个 Proposal 调配一个事务 ID(Zxid)

3.Leader 为每个 Follower 独自调配一个 FIFO 的队列,将须要播送的 Proposal 顺次放入到队列中

4.Follower 接管到 Proposal 后,首先将其以事务日志的形式写入到本地磁盘中,写入胜利后给 Leader 反馈一个 ACK 响应

5.Leader 接管到半数以上 Follower 的 ACK 响应后,即认为音讯发送胜利,能够发送 Commit 音讯

6.Leader 向所有 Follower 播送 Commit 音讯,同时本身也会实现事务提交。Follower 接管到 Commit 音讯后也会实现事务的提交

解体复原

在整个服务框架启动过程中,如果 Leader 服务器呈现网络中断、解体退出或重启等异常情况,ZAB 协定就会进入解体恢复模式。同时选举出新的 Leader 服务器。

当选举产生了新的 Leader 服务器,同时集群中曾经有过半的机器与该 Leader 服务器实现了状态同步(数据同步)之后,ZAB 协定会退出恢复模式。

1. 在 ZAB 协定中,为了保障程序的正确运⾏,整个复原过程完结后须要选举出⼀个新的 Leader 服务器。

2.Leader 选举算法不仅仅须要让 Leader ⾃身晓得曾经被选举为 Leader,同时还须要让集群中的所有其余机器也可能疾速地感知到选举产⽣进去的新 Leader 服务器。

ZAB 保证数据一致性

ZAB 协定规定了 如果⼀个事务 Proposal 在⼀台机器上被解决胜利,那么应该在所有的机器上都被解决胜利,哪怕机器呈现故障解体。针对这些状况 ZAB 协定须要保障以下条件:

  • 曾经在 Leader 服务器上提交的事务最终被所有服务器都提交。
    假如⼀个事务在 Leader 服务器上被提交了,并且曾经失去过半 Folower 服务器的 Ack 反馈,然而在它 将 Commit 音讯发送给所有 Follower 机器之前,Leader 服务器挂了
  • 抛弃只在 Leader 服务器上被提出(未提交)的事务。
    假如初始的 Leader 服务器 Server1 在提出了⼀个事务 Proposal3 之后就解体退出 了,从⽽导致集群中的其余服务器都没有收到这个事务 Proposal3。于是,当 Server1 恢复过来再次加 ⼊到集群中的时候,ZAB 协定须要确保抛弃 Proposal3 这个事务。

综上所述,ZAB 的选举进去的 Leader 必须满足以下条件:

可能确保提交曾经被 Leader 提交的事务 Proposal,同时抛弃曾经被跳过的事务 Proposal。即:

1. 新选举进去的 Leader 不能蕴含未提交的 Proposal。

2. 新选举的 Leader 节点中含有最大的 zxid。

ZAB 如何数据同步

所有失常运行的服务器要么成为 Leader,要么成为 Follower 并和 Leader 放弃同步。

1. 实现 Leader 选举(新的 Leader 具备最高的 zxid)之后,在正式开始⼯作(接管客户端申请)之前,Leader 服务器会⾸先确认事务⽇志中的所有 Proposal 是否都曾经被集群中过半的机器提交了,即 是否实现数据同步。

2.Leader 服务器须要确保所有的 Follower 服务器可能接管到每⼀条事务 Proposal,并且可能正确地将所有曾经提交了的事务 Proposal 应⽤到内存数据中。等到 Follower 服务器将所有其尚未同步的事务 Proposal 都从 Leader 服务器上同步过去并胜利应⽤到本地数据库中后,Leader 服务器就会将该 Follower 服务器加⼊到真正的可⽤ Follower 列表中,并开始之后的其余流程。

ZAB 运行时状态 #

ZAB 协定设计中,每个过程都有可能处于如下三种状态之一:

  • LOOKING:Leader 选举状态,正在寻找 Leader
  • FOLLOWING:以后节点是 Follower。与 Leader 服务器放弃同步状态
  • LEADING:以后节点是 Leader,作为主过程领导状态。

ZAB 状态的切换

启动时的状态转换
1. 所有过程的初始状态都是 LOOKING 状态,此时不存在 Leader。

2. 接下来,过程会试图选举进去一个新的 Leader,Leader 切换为 LEADING 状态,其它过程发现曾经选举出新的 Leader,那么它就会切换到 FOLLOWING 状态,并开始与 Leader 放弃同步。

3. 处于 FOLLOWING 状态的过程称为 Follower,LEADING 状态的过程称为 Leader。

4. 当 Leader 解体或者放弃领导位置时,其余的 Follower 过程就会切换到 LOOKING 状态开始新一轮的 Leader 选举。

运行过程中的状态转换
一个 Follower 只能和一个 Leader 放弃同步,Leader 过程和所有的 Follower 过程之间通过心跳监测机制来感知彼此的状况。

1. 若 Leader 可能在超时工夫内失常的收到心跳检测,那么 Follower 就会始终与该 Leader 放弃连贯。

2. 如果在指定工夫内 Leader 无奈从过半的 Follower 过程那里接管到心跳检测,或者 TCP 连贯断开,那么 Leader 会放弃以后周期的领导,并转换为 LOOKING 状态;其余的 Follower 也会抉择放弃这个 Leader,同时转换为 LOOKING 状态,之后会进行新一轮的 Leader 选举

ZAB 的四个阶段

选举阶段(Leader Election)
节点在一开始都处于选举阶段,只有有一个节点超过半数阶段的票数,它就能够入选准 Leader,只有达到第三个阶段(同步阶段),这个准 Leader 才会成为真正的 Leader。

这一阶段的目标就是为了选出一个准 Leader,而后进入下一阶段。

发现阶段
在这个阶段中,Followers 和上一轮选举出的准 Leader 进行通信,同步 Followers 最近承受的事务 Proposal。这个阶段次要目标是发现以后大多数节点承受的最新提议,并且准 Leader 生成新的 epoch,让 Followers 承受,更新它们的 acceptedEpoch。

一个 Follower 只会连贯一个 Leader,如果有一个节点 F 认为另一个 Follower P 是 Leader,F 在尝试连贯 P 时会被回绝,F 被回绝后,就会进入选举阶段。

同步阶段
同步阶段次要是利用 Leader 前一阶段取得的最新 Proposal 历史,同步集群中所有的正本。

只有当 quorum(超过半数的节点)都同步实现,准 Leader 才会成为真正的 Leader。Follower 只会接管 zxid 比本人 lastZxid 大的 Proposal。

播送阶段
到了这个阶段,Zookeeper 集群能力正式对外提供事务服务,并且 Leader 能够进行音讯播送。同时,如果有新的节点退出,还须要对新节点进行同步。须要留神的是,Zab 提交事务并不像 2PC 一样须要全副 Follower 都 Ack,只须要失去 quorum(超过半数的节点)的 Ack 就能够。

ZAB 协定实现

Java 版本的 ZAB 协定的实现跟下面的定义略有不同,选举阶段应用的是 Fast Leader Election(FLE),它蕴含了步骤 2 的发现职责。因为 FLE 会选举领有最新提议的历史节点作为 Leader,这样就省去了发现最新提议的步骤。

理论的实现将 发现和同步阶段合并为 Recovery Phase(复原阶段),所以,Zab 的实现实际上有三个阶段。

疾速选举(Fast Leader Election)

后面提到的 FLE 会选举领有最新 Proposal history(lastZxid 最大)的节点作为 Leader,这样就省去了发现最新提议的步骤。这是基于领有最新提议的节点也领有最新的提交记录

成为 Leader 的条件:

1. 选 epoch 最大的

2.epoch 相等,选 zxid 最大的

3.epoch 和 zxid 都相等,选 server_id 最大的(zoo.cfg 中配置的 myid)

节点在选举开始时,都默认投票给本人,当接管其余节点的选票时,会依据下面的 Leader 条件 判断并且更改本人的选票,而后从新发送选票给其余节点。当有一个节点的得票超过半数,该节点会设置本人的状态为 Leading,其余节点会设置本人的状态为 Following。

复原阶段(Recovery Phase)

这一阶段 Follower 发送他们的 lastZxid 给 Leader,Leader 依据 lastZxid 决定如何同步数据。这里的实现跟后面的 阶段 3 有所不同:Follower 收到 TRUNC 指令会终止 L.lastCommitedZxid 之后的 Proposal,收到 DIFF 指令会接管新的 Proposal。

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

播送阶段(Broadcast Phase)

参考 4.1 [ZAB 协定内容 #音讯播送]

ZAB 与 Paxos 的分割和区别

分割
1. 都存在一个相似 Leader 过程的角色,由其负责协调多个 Follower 过程的运行

2.Leader 过程都会期待超过半数的 Follower 作出正确的反馈后,才会将一个提议进行提交(过半准则)

3. 在 ZAB 中,每个 Proposal 中都蕴含了一个 epoch 值,用来代表以后 Leader 周期,在 Paxos 中同样存在这样的一个示意,名字为 Ballot。

区别

1.Paxos 算法中,新选举产生的主过程会进行两个阶段的工作;第一阶段称为读阶段:新的主过程和其余过程通信来收集主过程提出的提议,并将它们提交。第二阶段称为写阶段:以后主过程开始提出本人的提议。

2.ZAB 协定在 Paxos 根底上增加了同步阶段,此时,新的 Leader 会确保存在过半的 Follower 曾经提交了之前 Leader 周期中的所有事物 Proposal。这一同步阶段的引入,可能无效保障,Leader 在新的周期中提出事务 Proposal 之前,所有的过程都曾经实现了对之前所有事务 Proposal 的提交。

总的来说,ZAB 协定和 Paxos 算法的本质区别在于两者的设计目标不一样:ZAB 协定次要用于构建一个高可用的分布式数据主备零碎,而 Paxos 算法则用于构建一个分布式的一致性状态机零碎。

总结

问题解答:

1. 主从架构下,leader 解体,数据一致性怎么保障?

leader 解体之后,集群会选出新的 leader,而后就会进入复原阶段,新的 leader 具备所有曾经提交的提议,因而它会保障让 followers 同步已提交的提议,抛弃未提交的提议(以 leader 的记录为准),这就保障了整个集群的数据一致性。

2. 选举 leader 的时候,整个集群无奈解决写申请的,如何疾速进行 leader 选举?

这是通过 Fast Leader Election 实现的,leader 的选举只须要超过半数的节点投票即可,这样不须要期待所有节点的选票,可能尽早选出 leader。

起源 | https://urlify.cn/RRziQf

欢送关注我的微信公众号「码农解围」,分享 Python、Java、大数据、机器学习、人工智能等技术,关注码农技术晋升•职场解围•思维跃迁,20 万 + 码农成长充电第一站,陪有幻想的你一起成长

退出移动版