分布式与一致性协议之ZAB协议(三)

ZAB协议

主节点崩溃了,怎么办?

众所周知,系统在运行中不可避免会出现各种各样的问题,比如进程崩溃了、服务器死机了,这些问题会导致很严重的后果,让系统没办法继续运行。在ZAB协议中,写请求是必须在主节点上处理的,而且提案的广播和提交也是由主节点来完成的。既然主节点那么重要,如果它突然崩溃(宕机)了,该怎么办呢?

答案是选举出新的领导者(也就是新的主节点)。

在我看来,领导者选举关乎节点故障容错能力和集群可用性,是ZAB协议非常核心的设计之一。想象一下,如果没有领导者选举,主节点故障了,那么整个集群将无法写入,这将是极其严重的灾难性故障。理解领导者选举(也就是快速领导者选举,Fast Leader Election),能帮助我们更深刻地理解ZAB协议,也能在日常工作中更游刃有余地处理集群的可用性问题。比如写请求持续失败时,可以先排查下集群的节点状态。

既然领导者选举这么重要,那么ZAB协议是如何选举领导者的呢?

ZAB协议是如何选举领导者的

既然要选举领导者,那就会涉及成员身份变更,那么ZAB协议支持哪些成员身份呢?

如何选举





为了更好地理解ZAB的领导者选举,仍然用一个例子演示一下。为了方便演示和理解(我们聚焦最核心的领导者PK),假设投票信息的格式是<proposedLeader,proposedEpoch,proposedLastZxid,node>,具体如下:

  • 1.proposedLeader:节点提议的领导者的集群ID,也就是在集群配置(比如myid配置文件)时指定的ID
  • 2.proposedEpoch:节点提议的领导者的任期编号
  • 3.proposedLastZxid:节点提议的领导者的事务标识符的最大值(也就是最新提案的事务标识符)
  • 4.node:投票的节点,比如节点B.

假设一个ZooKeeper集群由节点A、B、C组成,其中节点A是领导者,节点B、C是跟随者(为了方便演示,假设节点B、C的epoch分别就是1和1,lastZxid分别是101和102,集群ID分别为2和3),如图所示。如果节点A宕机了,如何选举领导者呢?

首先,当跟随者检测到连接领导者节点的读操作等待超时时,跟随者会将自己的节点状态变更成LOOKING,然后发起领导者选举(为了演示方便,我们假设这时节点B、C都已经检测到了读操作超时),如图所示。

接着,每个节点会创建一张选票,这张选票是投给自己的,也就是说,节点B、C都"自告奋勇"地推荐自己为领导者并创建选票<2,1,101,B>和<3,1,102,C>,然后各自将选票发送给集群中的所有节点,也就是说,节点B发送给节点B、C,节点C也发送给节点B、C.

  • 一般而言,节点会先接收自己发送给自己的选票(因为不需要跨节点通信,传输速度更快),也就是说,节点B会先收到来自节点B的选票,节点C会先收到来自节点C的选票,如图所示。
    需要注意的是,集群的个节点收到选票后,为了选举出数据最完整的节点,对于每一张接收到的选票,节点都需要进行领导者PK,也就是将选票提议的领导者和自己提议的领导者进行比较,找出更适合作为领导者的节点。约定的规则如下:
  • 1.优先检查任期编号,任期编号大的节点作为领导者
  • 2.如果任期编号相同,则比较事务标识符的最大值,值大的节点作为领导者
  • 3.如果事务标识符的最大值也相同,再比较集群ID,集群ID大的节点作为领导者。
    如果选票提议的领导者比自己提议的领导者更适合作为领导者,那么节点将调整选票内容,推荐选票提议的领导者作为领导者。
    当节点B、C接收到选票后,因为选票提议的领导者与自己提议的领导者相同,所以,领导者PK的结果是节点B、C不需要调整选票信息,只需要正常接收和保存选票就可以了,如图所示。

接着节点B、C分别接收到来自对方的选票,比如节点B接收到来自节点C的选票,节点C接收到来自节点B的选票,如图所示。

对于节点C而言,它提议的领导者是节点C,而选票(<2,1,101,B>)提议的领导者是节点B,因为节点C的任期编号与节点B相同,但节点C的事务标识符的最大值比节点B的大,所以,按照约定的规则,相比节点B,节点C更适合作为领导者,也就是说,节点C不需要调整选票信息,正常接收和保存选票就可以了。但对于节点B而言,它提议的领导者是节点B,选票(❤️,1,102,C>)提议的领导者节点是C,因为C的任期编号与节点B相同,但节点C的事务标识符的最大值比节点B的大,所以,按照约定的规则,相比节点B,节点C应该作为领导者,也就是说,节点B除了接收和保存选票信息,还会更新自己的选票为<3,1,102,B>,即推荐节点C作为领导者,并将选票重新发送给节点B、C,如图所示。

接着,当节点B、C接收到来自节点B的新的选票时,因为这张选票(❤️,1,102,B>)提议的领导者,与它们提议的领导者是一样的,都是节点C,所以,它们正常接收和保存这张选票就可以了,如图所示。

最后,因为此时节点B、C提议的领导者(节点C)赢得了大多数选票(两张选票),所以,节点B、C将根据投票结果变更节点状态,并退出选举。比如因为当选的领导者是节点C,那么节点B将变更为FOLLOWING并退出选举,而节点C将变更状态为LEADING并退出选举,如图所示。

至此,我们就选举了新的领导者(节点C).这个选举的过程很容易理解,这里只是假设了一种选举的情况,实际上还会存在节点间事务标识符相同、节点在广播投票信息前接收到其他节点的投票等情况。

相关推荐
2501_916766544 分钟前
解决idea依赖导入不成功的问题
java·intellij-idea
头发还在的女程序员7 分钟前
基于JAVA语言的短剧小程序-抖音短剧小程序
java·开发语言·小程序
vir0216 分钟前
P12155 [蓝桥杯 2025 省 Java B] 消失的蓝宝
java·职场和发展·蓝桥杯
z***89711 小时前
【分布式】Hadoop完全分布式的搭建(零基础)
大数据·hadoop·分布式
爱笑的眼睛111 小时前
PyTorch Lightning:重新定义深度学习工程实践
java·人工智能·python·ai
Kevinyu_2 小时前
责任链模式
java·hadoop·责任链模式
明洞日记2 小时前
【设计模式手册012】责任链模式 - 请求处理的流水线艺术
java·设计模式·责任链模式
q***07142 小时前
Java实战:Spring Boot application.yml配置文件详解
java·网络·spring boot
雨中飘荡的记忆2 小时前
Spring Alibaba AI 实战指南
java·ai编程
冰封剑心2 小时前
MiniCPM-V-2_6 (4-bit 量化)使用
java·前端·数据库