网易二面:ZooKeeper的ZAB协议工作原理是什么?

文章内容收录到个人网站,方便阅读:http://hardyfish.top/

ZAB(Zookeeper Atomic Broadcast)是 ZooKeeper 专门设计的一种原子广播协议,用于保证 数据一致性故障恢复。它主要用于 主从复制(Leader-Follower) ,并确保 写请求(事务)严格有序,同时保证集群在发生 Leader 失效 时能正确恢复。

1. ZAB 协议核心目标

  1. 保证数据一致性 ZooKeeper 采用 强一致性(Linearizability) ,所有写入(事务)按顺序执行。
  2. 支持主从复制 通过 Leader 负责写操作,Follower 只进行读操作,确保数据同步。
  3. 故障恢复(Crash Recovery) 发生故障后,保证恢复一致状态,并选举新 Leader 继续服务。

2. ZAB 工作流程

ZAB 主要由两个阶段组成:

  1. 崩溃恢复(Crash Recovery)阶段:当 Leader 崩溃或网络分区时,集群需要选举一个新的 Leader 并同步数据,确保一致性。
  2. 消息广播(Atomic Broadcast)阶段:当集群稳定后,Leader 通过 ZAB 协议进行事务同步,确保所有 Follower 都接收到相同的事务。

2.1 崩溃恢复阶段(Leader 选举 & 数据同步)

如果 ZooKeeper 发现 Leader 宕机或发生了网络分区,它会进入 恢复模式,重新选举新的 Leader 并确保数据一致。

步骤

  1. 选举 Leader: 使用 ZAB 选举算法(基于 ZXID 最大值)。拥有最大事务 ID(ZXID)的节点 优先成为 Leader。选举完成后,Leader 进入 "LOOKING" 状态,等待 Follower 连接。
  2. 同步数据: Follower 连接到新的 Leader,检查 Leader 最新的数据状态。如果 Follower 落后于 Leader,Leader 发送缺失的事务日志,Follower 进行同步。只有当大多数(Quorum)Follower 完成同步后,Leader 才能进入 BROADCAST(广播)模式,开始正常处理请求。

2.2 消息广播阶段(Atomic Broadcast)

当 Leader 进入 正常状态(Broadcasting) 后,它会通过 ZAB 原子广播协议 处理事务请求。

写请求流程

  1. 客户端发送写请求到 Leader
  2. Leader 生成全局递增的事务 ID(ZXID) : ZXID = [epoch(时期) | counter(递增计数)]确保所有事务有全局唯一的执行顺序。
  3. Leader 发送 PROPOSAL 给所有 Follower : 事务以 PROPOSAL 形式广播给所有 Follower。
  4. Follower 接收 PROPOSAL 并返回 ACK: 当过半 Follower (Quorum) 确认后,Leader 发送 COMMIT。
  5. Leader 发送 COMMIT 并持久化: Leader 持久化事务日志 并发送 COMMIT 给所有 Follower。Follower 执行事务 并返回确认。

示例

客户端  -> Leader  -> Follower1, Follower2, Follower3
   写请求  ->  事务 ZXID=0x10001 (Proposal)  ->  Ack
              <-   事务已提交 (Commit)    <-

3. ZAB 关键特性

3.1 ZXID(Zookeeper Transaction ID)

  • 全局唯一事务 ID,格式如下:epoch(时期) :每次 Leader 选举时递增,标记不同的 Leader 时代。counter(计数器) :在同一时代内,每个事务递增,保证顺序。

示例

  • 0x10000001 代表 epoch=1, counter=1
  • 0x10000002 代表 epoch=1, counter=2

作用

  • 通过 ZXID 选举 Leader(拥有最大 ZXID 的服务器会当选)。
  • 事务严格按照 ZXID 顺序执行,确保一致性。

3.2 选举算法

ZooKeeper 采用 Fast Leader Election(FLE) 选举算法:

  • 选举过程中,服务器会向其他服务器发送投票,选择 ZXID 最大的节点 作为 Leader。
  • 只有当超过半数(Quorum) 的节点确认后,Leader 才能正式生效。

3.3 事务一致性

ZAB 采用 过半确认机制(Quorum) ,确保 Leader 提交事务前,至少半数 Follower 先收到:

  • 只有当 N/2 + 1 以上的 Follower 确认后,事务才会 COMMIT
  • 这样即使部分 Follower 宕机,事务仍然可以继续。

4. ZAB vs Paxos vs Raft

ZAB

ZooKeeper

强一致性

适用于

主从复制

,支持崩溃恢复

Paxos

分布式共识协议

适用于

分布式数据库

,但实现复杂

Raft

简化版 Paxos

适用于

分布式 KV 存储

,选举更高效

5. 总结

  • ZAB 主要用于 ZooKeeper 复制和一致性保证,由 崩溃恢复 + 原子广播 组成。
  • Leader 负责处理写请求,Follower 负责读请求,通过 ZAB 原子广播协议 保证数据一致。
  • 事务采用 ZXID 严格有序提交,通过 过半确认(Quorum)机制 确保强一致性。
  • 如果 Leader 崩溃,ZAB 进入恢复模式,选举最大 ZXID 服务器作为新的 Leader

💡 总结一句话: ZAB 通过 Leader-Follower 复制 + 事务广播,确保 ZooKeeper 在 高可用、强一致 的分布式环境下正确运行。

#面试题##面试#
大厂面试每日一题 文章被收录于专栏

大厂每日一道面试题!

全部评论
mark
点赞 回复 分享
发布于 09-28 15:31 四川
mark学习了
点赞 回复 分享
发布于 09-27 00:12 湖南
uu是平台开发嘛
点赞 回复 分享
发布于 09-24 20:54 广东

相关推荐

09-19 15:57
南开大学 Java
📍面试公司:字节🕐面试时间:9月19💻面试岗位:后端❓面试问题:只说我觉得稍微有难度的,基础的不写了一.八股1.ARP欺骗是什么(先问的我输入一个网址到回显的过程,我中途提到了arp会去找mac地址,然后就问我ARP欺骗是什么,凭感觉说了下)2.消息队列怎么保证三个层面可靠性,有序性,不丢失?3.消息队列有很多个,如何取舍选择哪个呢?4.详细说说堆这个数据结构5.进程间通信方式?各自的优缺点。二.场景题你有一台机器,很小的内存,现在你有一个很大的日志,日志里面只记录了IP地址,实现一个算法找出访问次数最大的IP(我说用hash,面试官说ip都装不下,你map里又要记录ip又要记录次数,能装下吗?后面说分治)三.项目1.为什么用http和mq通信?为什么不用RPC?2.消息队列如何保证不重复消费?存在redis里的话用什么数据结构?什么时候移除?3.这个项目有哪些表?追问订单信息这个表构建索引了吗?应该怎么对这个表构建索引?哪些字段加索引?4.讲讲微服务间如果通信?讲讲锁单/结算/退单流程?5.讲讲动态配置中心怎么实现的?限流器怎么实现的,为什么用本地缓存,能用redis吗,redis怎么实现限流器?四.手撕删除倒数第n个链表节点(面试官有点皮,故意让我输入需要特判的情况,比如n大于链表长度了,比如删除了链表的头节点)🙌面试感想:还行,百分之95都答上了,继续加油!!!
查看12道真题和解析
点赞 评论 收藏
分享
投的java岗,投的时候看到岗位要求里是精通至少一门编程语言(Java/Golang),就带着我的golang版本的简历去面了。结果一上来就被让解释为什么拿着go简历投java,解释了一通后感觉对面好像不是很满意。📍面试公司:携程🕐面试时间:50min💻面试岗位:java后端开发❓面试问题:1.&nbsp;那你用一两点总结一下,你觉得&nbsp;Go&nbsp;和&nbsp;Java&nbsp;最大的区别在哪里?2.&nbsp;那&nbsp;RocketMQ&nbsp;是怎么保证消息可靠性的?3.&nbsp;好的,那在使用&nbsp;RocketMQ&nbsp;重试功能时,需要注意些什么呢?4.&nbsp;那在失败场景下,如果出现大量重试,首先要考虑失败原因,比如是不是下游服务扛不住了,这也是一种可能的失败场景。如果这种情况下还一直在批量重试,可能会导致下游服务的压力进一步升级,那基于这方面考虑,我们有哪些手段可以预防或避免这种情况呢?5.&nbsp;你可以站在两个角度思考:一是作为下游&nbsp;A&nbsp;服务的提供者,二是作为调用&nbsp;A&nbsp;服务的消费方。假设这两个系统都是你负责的。那你要怎么保证整个系统的稳定性?分别对应的应该做哪些调整?6.&nbsp;这个暂停是出于什么考虑呢?那在什么情况下会选择暂停呢?这种情况下,按你说的,流量大的时候反而要暂停调用下游服务,这不是和实际业务需求不符吗?7.&nbsp;那暂停要停多久呢?什么时候恢复呢?8.&nbsp;那我再问一个问题,你多次提到&nbsp;“根据监控来做决策”,但如果有很多业务场景、很多系统,都需要投入大量精力做监控,还要求看监控的人具备调控系统的能力,这显然不现实,怎么解决这个问题呢?9.&nbsp;自动告警机制确实是个好方法。那告警之后呢?系统后续该怎么运行,才能形成一个闭环,确保业务能继续推进?10.&nbsp;那什么时候需要人工去恢复系统正常运行呢?11.&nbsp;对,那你这个很很明显的一个问题就是人工嘛,这个我刚才也说了,要求人工有这个能力。它不仅仅是一个系统,它可能很多个系统。如果你采用这个架构去设计的话,你会有很多很多这种东西要去看。比如我们做卖票业务,假设有很多代理人,还有很多航司网站,国内有几十家航司,国外也有不少。那每一个航司它可能都是有一个类似的一个产品设计,对不对?那要是某天东航扛不住了,就要处理东航的问题;明天国航、南航等多家航司同时出问题,就需要很多人去处理。假设都用同一种方案,成百上千个系统都这样设计,人工根本忙不过来,这现实吗?就是一个我能做,10&nbsp;个还勉强能行。当成百上千的时候,这个人还能玩得过来吗?我就把问题抛得这么严重,我们现在系统就是一个典型的生态,就会有这种问题。那我们该怎么去思考这个问题?12.&nbsp;那再问一个关于&nbsp;RocketMQ&nbsp;的问题,你之前提到了顺序消费,那&nbsp;MQ&nbsp;的消息有序性会在哪些阶段出现问题?什么情况下会导致消息无序?13.&nbsp;那再假设一个场景:生产者生成消息&nbsp;ID&nbsp;后,发送消息时突然挂掉了,因为之前提到用事务提交,这种情况下消息可能发送失败,导致消息断档。那消费方那边,他在消费的时候,他一直在等上一条消息。那消费者其实不用一直等,也可以处理后面的消息,但这样就会破坏有序性。那消费者怎么知道有一条消息中断了呢?比如消息&nbsp;ID&nbsp;从&nbsp;1&nbsp;到&nbsp;10,发送&nbsp;ID&nbsp;为&nbsp;2&nbsp;的消息时失败了,消费者消费完&nbsp;ID&nbsp;为&nbsp;1&nbsp;的消息后,按逻辑该等&nbsp;ID&nbsp;为&nbsp;2&nbsp;的消息,但&nbsp;ID&nbsp;为&nbsp;2&nbsp;的消息永远不会来了。14.&nbsp;那不等的话直接消费到第四条消息怎么办,因为2后面还有34,如果不等2的话先消费4怎么办15.&nbsp;redis使用经验讲讲16.&nbsp;redis持久化机制有哪些17.&nbsp;缓存穿透、击穿、雪崩18.&nbsp;缓存击穿时,分布式锁是在什么时候加载的19.&nbsp;用分布式锁的话会让大量用户请求等待,有没有更好的解决方案20.&nbsp;多级缓存为什么能解决这个问题21.&nbsp;MySQL事务隔离级别22.&nbsp;mvcc怎么实现可重复读23.&nbsp;MySQL的exist和in的区别24.&nbsp;为什么不用select&nbsp;*&nbsp;查询25.&nbsp;索引失效的场景有哪些27.&nbsp;设计索引参考哪些原则
查看10道真题和解析
点赞 评论 收藏
分享
评论
1
3
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务