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

news2024/11/26 8:20:52

ZAB协议

成员发现

成员发现是通过跟随者和领导者交互来完成的,目标是确保大多数节点对领导者的关系没有异议,也就是确立领导者的领导地位。成员发现的实现流程如图所示。
在这里插入图片描述

  • 1.领导者选举结束,节点进入跟随者状态或者领导者状态后,会分别设置ZAB状态为成员发现状态,具体如下:
    1.1 跟随者会调用Follower.followLeader()函数,设置ZAB状态为成员发现状态,如代码所示
self.setZabState(QuorumPeer.ZabState.DISCOVERY);

1.2 领导者会调用Leader.lead()函数,并设置ZAB状态为成员发现状态,如代码所示

self.setZabState(QuorumPeer.ZabState.DISCOVERY);
  • 2.跟随者会主动联系领导者,发送自己已接收的领导者任期编号的最大值(也就是acceptedEpoch)的FOLLOWINFO消息给领导者,如代码所示
// 跟领导者建立网络连接
connectToLeader(leaderServer.addr, leaderServer.hostname);
connectionTime = System.currentTimeMills();
// 向领导者报道,并获取领导者的事务标识符最大值
long newEpochZxid = registerWithLeader(Leader.FOLLOWERINFO);
  • 3.在接收到来自跟随者的FOLLOWINFO消息后,在LearnerHandler.run()函数中,领导者将创建包含自己的事务标识符最大值的LEADINFO消息,并响应给跟随者,如代码所示
// 创建LEADINFO消息
QuorumPacket newEpochPacket =
new QuorumPacket(Leader.LEADERINFO, newLeaderZxid, ver, null);
// 发送LEADINFO消息给跟随者
oa.writeRecord(newEpochPacket, "packet");
  • 4.在接收到来自领导者的LEADINFO消息后,跟随者会基于领导者的任期编号判断领导者是否合法,如果领导者不合法,则发起新的选举,如果领导者合法,则响应ACKEPOCH消息给领导者,如代码所示
// 创建ACKEPOCH消息,包含已提交提案的事务标识符最大值
QuorumPakcet ackNewEpoch =
new QuorumPacket(Leader.ACKEPOCH, lastLoggedZxid, epochBytes, null);
// 响应ACKEPOCH消息给领导者
writePacket(ackNewEpoch, true);
  • 5.跟随者设置ZAB状态为数据同步状态,如代码所示
self.setZabState(QuorumPeer.ZabState.SYNCHRONIZATION);
  • 6.在LearnerHandler.run()函数中(以及Leader.lead()函数),领导者会调用waitForEpochAck()函数来阻塞和等待来自大多数节点的ACKEPOCH消息,如代码所示
ss = new StateSummary(bbepoch.getInt(), ackEpochPacket.getZxid());
learnerMaster.waritForEpochAck(this.getSid(), ss)
  • 7.在接收到来自大多数节点的ACKEPOCH消息后,在Leader.lead()函数中,领导者设置ZAB状态为数据同步状态。
self.setZabState(QuorumPeer.ZabState.SYNCHRONIZATION);

这样,ZooKeeper就实现了成员发现,且各节点就领导者的领导关系达成了共识。当跟随者和领导者设置ZAB状态为数据同步状态后,它们就进入了数据同步阶段。那么ZooKeeper中的数据同步是如何实现的呢?

数据同步

数据同步也是通过跟随者和领导者交互来完成的。目标是确保跟随者节点上的数据与领导者节点上的数据一直。数据同步的实现流程如图所示。
在这里插入图片描述

  • 1.在LearnerHandler.run()函数中,领导者调用syncFollower()函数,根据跟随者的事务标识符的最大值判断用哪种方式处理不一致数据,并把已提交提案和未提交提案都同步给跟随者,如代码所示
peerLastZxid = ss.getLastZxid();
boolean needSnap = syncFollower(peerLastZxid, learnerMaster);

在这里,你需要了解领导者向跟随者同步数据的3种方式(TRUNC、DIFF、SNAP),它们分别代表什么含义呢?要想了解这部分内容,首先要了解一下syncFollower()中3个关键变量的含义。
1.peerLastZxid:跟随者节点上提案的事务标识符欸度最大值
2.maxCommittedLog、minCommittedLog:领导者节点内存队列中已提交提案的事务标识符的最大值和最小值。需要注意的是,maxCommittedLog、minCommittedLog与ZooKeeper的设计有关。在ZooKeeper中,为了更高效地将提案复制到跟随者,领导者会将一定数量(默认值为500)的已提交提案放在内存队列里,而maxCommittedLog、minCommittedLog分别标识的是内存队列中已提交提案的事务标识符最大值和最小值。

说完3个关键变量,再来说说3种同步方式。
1.TRUNC:当peerLastZxid大于maxCommittedLog时,领导者会通知跟随者丢弃超出的那部分提案。比如,如果跟随者的peerLastZxid为11,领导者的maxCommittedLog为10,那么领导者将通知跟随者丢弃事务标识符值为11的提案
2.DIFF:当peerLastZxid小于maxCommittedLog但大于minCommittedLog时,领导者会向跟随者同步缺失的已提交的提案,比如,如果跟随者的peerLastZxid为9,领导者的maxCommittedLog为10,minCommittedLog为9,那么领导者将同步事务标识符值为10的提案给跟随者
3.SNAP:当peerLastZxid小于minCommittedLog时,也就是说,跟随者缺失的提案比较多,那么领导者会同步快照数据给跟随者,并直接覆盖跟随者本地的数据。
在这里,补充一下,领导者先就已提交提案和跟随者达成一致,然后调用learnerMaster.startForwarding()将未提交提案(如果有的话)也缓存发送队列(queuedPackets),并最终复制给跟随者。也就是说,领导者是以自己的数据为准,实现各节点数据副本的一致的。
需要注意的是,在syncFollower()种,领导者只是将需要发送的差异数据缓存在发送队列,还没有实际发送

  • 2.在LearnerHandler.run()函数种,领导者创建NEWLEADER消息并缓存在发送队列种,如代码所示:
// 创建NEWLEADER消息
QuorumPacket newLeaderQP =
new QuorumPacket(Leader.NEWLEADER, newLeaderZxid,learnerMaster.getQuorumVerifierBytes(), null);
// 缓存NEWLEADER消息到发送队列中
queuedPackets.add(newLeaderQP);
  • 3.在LearnerHandler.run()函数中,领导者调用startSendingPackets()函数启动一个新线程,并将缓存的数据发送给跟随者,如代码所示
// 发送缓存队列中的数据
startSendingPackets();
  • 4.跟随者调用syncWithLeader()函数,处理来自领导者的数据同步,如代码所示
// 处理数据同步
syncWithLEader(newEpochZxid);
  • 5.在syncWithLeader()函数中,跟随者在接收到来自领导者的NEWLEADER消息后,返回确认响应给领导者,如代码所示
writePacket(new QuorumPacket(Leader.ACK, newLeaderZxid, null, null), true);
  • 6.在LearnerHandler.run()函数(以及Leader.lead()函数)中,领导者等待来自大多数节点的NEWLEADER消息的响应,如代码所示
learnerMaster.waitForNewLeaderAck(getSid(), qp.getZxid());
  • 7.当接收到来自大多数节点的NEWLEADER消息的响应时,在Leader.lead()函数中,领导者设置ZAB状态为广播状态,如代码所示
self.setZabState(QuorumPeer.ZabState.BROADCAST);

同时,在LearnerHandler.run()中发送UPTODATE消息给所有跟随者,通知它们数据同步已经完成了,如代码所示

queuedPackets.add(new QuorumPacket(Leader.UPTODATE, -1, null, null));
  • 8.跟随者在接收到UPTODATE消息后会直到数据不一致已修复,可以处理写请求了,同时设置ZAB状态为广播状态
// 数据同步完成后,跟随者就可以正常处理来自领导者的广播消息了,同时设置ZAB状态为广播状态
self.setZabState(QuorumPeer.ZabState.BROADCAST);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1651008.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微软 AI 研究团队推出 SIGMA:一个开源研究平台,旨在推动混合现实与人工智能交叉领域的研究与创新

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

YzmCMS 7.0任意函数调用RCE 漏洞研究分析

YzmCMS是一款基于YZMPHP开发的一套轻量级开源内容管理系统,YzmCMS简洁、安全、开源、免费,可运行在Linux、Windows、MacOSX、Solaris等各种平台上,专注为公司企业、个人站长快速建站提供解决方案。 YzmCMS 某些接口调用了 db_pdo类的where方法 导致了远程命令执行漏洞&#xf…

PLC学习笔记

PLC学习笔记 前言一、一些基操知识二、GX works2编程2.1 位逻辑1.2 中间寄存器1.3 PLC的扫描方式 总结 前言 我这个人真的是太渴望知识了~ 一、一些基操知识 一般X表示输入,Y表示输出。一般八个为一组X0~X7M表示中间寄存器,M0~M7时间T、计数C 二、GX …

操作系统:线程相关知识

目录 1.生产消费者模型 1.1.概念引入 1.2.基于阻塞队列的生产消费模型 1.3.POSIX信号量 1.3.1.再识信号量 1.3.2.信号量接口的学习 1.4.基于环行队列的生产消费模型 1.5.深刻理解生产消费模型 2.可重入函数与线程安全 1.生产消费者模型 1.1.概念引入 生产者-消费者模型…

AI换脸免费软件Rope中文汉化蓝宝石版本全新UI界面,修复部分已知错误【附下载地址与详细使用教程】

rope蓝宝石版:点击下载 注意:此版本支持N卡、A卡、CPU,且建议使用中高端显卡,系统要求win10及以上。 Rope-蓝宝石 更新内容: 0214版更新: ①(已修复)恢复到以前的模型荷载参数。有…

Hadoop3:HDFS的架构组成

一、官方文档 我这里学习的是Hadoop3.1.3版本,所以,查看的也是3.1.3版本的文档 Architecture模块最下面 二、HDFS架构介绍 HDFS架构的主要组成部分,是一下四个部分 1、NameNode(NN) 就是Master节点,它是集群管理者。 1、管…

Stack数据结构设计模板

第三章 栈、队列、数组 1.栈 1.1 顺序栈 #define MaxSize 20 typedef int ElemType; //顺序栈的定义 typedef struct {ElemType data[MaxSize];int top; }SqStack; // 初始化顺序栈 void InitSqStack(SqStack &S){S.top -1; }; // 入栈(增) bool Push(SqStack &S,El…

RabbitMQ之消费者并发消费

为什么要引入消费者的并发消费? 当生产者的推送速度是远远超过消费者的能力的,可以提高消费者的消费速度。比如在java中我们可以启动多个 JVM 进程,实现多进程的并发消费,从而加速消费的速度,在mq中也可以通过设置配置…

Git系列:Git Stash临时保存与恢复工作进度

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

python从0开始学习(五)

目录 前言 1、顺序结构 2、选择结构 2.1双分支结构 2.2多分枝结构 2.3嵌套使用 2.4多个条件的链接 总结 前言 在上篇文章中,我们学习了python中的运算符,本篇文章继续往下讲解。本篇文章主要讲解程序的组织结构。 1、顺序结构 顺序结构是程序按照…

UDP通讯的demo

udp通讯的demo,这个只是简单的实现。 后面我还会加入udp组播功能。 因为懒,所以我自己发,自己接收了。 经过测试,可以看到,发送消息和接收消息功能都没问题。 广播: 这个是点对点的通过对方的ip和端口发…

设计模式学习笔记 - 回顾总结:在实际软件开发中常用的设计思想、原则和模式

概述 本章,先来回顾下整个专栏的知识体系,主要包括面向对象、设计原则、编码规范、重构技巧、设计模式五个部分。 面向对象 相对于面向过程、函数式编程,面向对象是现在最主流的编程范式。纯面向过程的编程方法,现在已经不多见了…

网络网络层之(4)IPv4协议

网络网络层之(1)IPv4协议 Author: Once Day Date: 2024年4月4日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文档可参考专栏:通信网络技术_Once-Day的…

设置 kafka offset 消费者位移

文章目录 1.重设kafka消费者位移2.示例2.1 通过 offset 位置2.2 通过时间2.3 设置到最早 1.重设kafka消费者位移 维度策略含义位移Earliest把位移调整到当前最早位移处位移Latest把位移调整到当前最新位移处位移Current把位移调整到当前最新提交位移处位移Specified-Offset把位…

奥威-金蝶BI现金流量表模板,可借鉴、可套用

企业现金流一旦出了问题都是大问题,会直接影响到企业的日常运作,甚至直接关系到企业能不能继续存活,因此现金流量表是企业财务分析中重要报表之一,也是企业监控财务监控情况的重要手段之一。那么这么重要的一份现金流量表该怎么做…

Angular中创建和使用服务

Angular中的服务 文章目录 Angular中的服务前言一、创建服务二、使用服务 前言 Angular 服务是 Angular 应用程序中用于封装可重用逻辑的类。服务在应用程序的多个组件之间共享数据和功能,而不依赖于应用程序的UI。服务可以用于诸如数据处理、与后端通信、用户身份…

Verilog中4位数值比较器电路

某4位数值比较器的功能表如下。 请用Verilog语言采用门级描述方式,实现此4位数值比较器 参考代码如下: (CSDN代码块不支持Verilog,代码复制到notepad编辑器中,语言选择Verilog,看得更清楚) t…

芸众商城电商专业版400+插件源码+搭建教程

介绍: 芸众商城社交电商系统SAAS平台前端基于vue开发,后端基于研发积分商城系统源码 php,本文安装芸众商城全插件(400多个)商业版平台源码,可同时支持多端口部署运行;使用宝塔面板一键部署的形…

Linux:进程等待 进程替换

Linux:进程等待 & 进程替换 进程等待wait接口statuswaitpid接口 进程替换exec系列接口 当一个进程死亡后,会变成僵尸进程,此时进程的PCB被保留,等待父进程将该PCB回收。那么父进程要如何回收这个僵尸进程的PCB呢?父…

bfs之八数码

文章目录 八数码解题思路图解举例算法思路 代码CPP代码Java代码 八数码 在一个 33的网格中,1∼8这 8个数字和一个 x 恰好不重不漏地分布在这 33 的网格中。 例如: 1 2 3 x 4 6 7 5 8在游戏过程中,可以把 x 与其上、下、左、右四个方向之一…