PBFT算法

在我的博客中对于RAFT算法也有详细的介绍,raft算法包含三种角色,分别是:跟随者( follower ),候选人(candidate )和领导者( leader )。集群中的一个节点在某一时刻只能是这三种状态的其中一种,这三种角色是可以随着时间和条件的变化而互相转换的。

raft 算法主要有两个过程:一个过程是领导者选举,另一个过程是日志复制,其中日志复制过程会分记录日志和提交数据两个阶段。raft 算法支持最大的容错故障节点是(N-1)/2,其中 N 为 集群中总的节点数量。

国外有一个动画介绍raft算法介绍的很透彻,链接地址为:http://thesecretlivesofdata.com/raft/。这个动画主要包含三部分内容,第一部分介绍简单版的领导者选举和日志复制的过程,第二部分内容介绍详细版的领导者选举和日志复制的过程,第三部分内容介绍的是如果遇到网络分区(脑裂),raft 算法是如何恢复网络一致的。有兴趣的朋友可以结合这个动画以及我的博客来更好的理解raft算法。这篇博客主要来讲解学习PBFT算法。

RAFT共识-CSDN博客https://blog.csdn.net/qq_45875349/article/details/139673531


1. 背景

pbft 算法的提出主要是为了解决拜占庭将军问题。什么是拜占庭将军问题呢?拜占庭位于如今的土耳其的伊斯坦布尔,是古代东罗马帝国的首都。拜占庭罗马帝国国土辽阔,为了达到防御目的,每块封地都驻扎一支由将军统领的军队,每个军队都分隔很远,将军与将军之间只能靠信差传递消息。 在战争的时候,拜占庭军队内所有将军必需达成一致的共识,决定是否有赢的机会才去攻打敌人的阵营。但是,在军队内有可能存有叛徒和敌军的间谍,左右将军们的决定影响将军们达成一致共识。在已知有将军是叛徒的情况下,其余忠诚的将军如何达成一致协议的问题,这就是拜占庭将军问题。

详细的内容可以看我的博客:有趣的拜占庭将军问题与BFT算法-CSDN博客

拜占庭将军问题最早是由 Leslie Lamport 与另外两人在 1982 年发表的论文《The Byzantine Generals Problem 》提出的, 他证明了在将军总数大于 3f ,背叛者为f 或者更少时,忠诚的将军可以达成命令上的一致,即 3f+1<=n 。算法复杂度为 o(n^(f+1)) 。而 Miguel Castro (卡斯特罗)和 Barbara Liskov (利斯科夫)在1999年发表的论文《 Practical Byzantine Fault Tolerance 》中首次提出 pbft 算法,该算法容错数量也满足 3f+1<=n ,算法复杂度为 o(n^2)。

2. PBFT算法的最大容错节点

pbft 算法的除了需要支持容错故障节点之外,还需要支持容错作恶节点。假设集群节点数为 N,有问题的节点为 f。有问题的节点中,可以既是故障节点,也可以是作恶节点,或者只是故障节点或者只是作恶节点。那么会产生以下两种极端情况:

  1. 第一种情况,f 个有问题节点既是故障节点,又是作恶节点,那么根据小数服从多数的原则,集群里正常节点只需要比f个节点再多一个节点,即 f+1 个节点,确节点的数量就会比故障节点数量多,那么集群就能达成共识。也就是说这种情况支持的最大容错节点数量是 f =(n-1)/2 ,2f + 1 = n
  2. 第二种情况,故障节点和作恶节点都是不同的节点。那么就会有 f 个问题节点和 f 个故障节点,当发现节点是问题节点后,会被集群排除在外,剩下 f 个故障节点,那么根据小数服从多数的原则,集群里正常节点只需要比f个节点再多一个节点,即 f+1 个节点,确节点的数量就会比故障节点数量多,那么集群就能达成共识。所以,所有类型的节点数量加起来就是 f+1 个正确节点,f个故障节点和f个问题节点,即 3f+1=n。

3. 算法核心流程

pbft 算法的基本流程主要有以下四步:

  1. 客户端发送请求给主节点
  2. 主节点广播请求给其它节点,节点执行 pbft 算法的三阶段共识流程。
  3. 节点处理完三阶段流程后,返回消息给客户端。
  4. 客户端收到来自 f+1 个节点的相同消息后,代表共识已经正确完成。

为什么收到 f+1 个节点的相同消息后就代表共识已经正确完成?从上一小节的推导里可知,无论是最好的情况还是最坏的情况,如果客户端收到 f+1 个节点的相同消息,那么就代表有足够多的正确节点已全部达成共识并处理完毕了。

4. 算法核心三阶段流程

下面介绍 pbft 算法的核心三阶段流程,如下图所示:

算法的核心三个阶段分别是 pre-prepare 阶段(预准备阶段),prepare 阶段(准备阶段), commit 阶段(提交阶段)。图中的C代表客户端,0,1,2,3 代表节点的编号,打叉的3代表可能是故障节点或者是问题节点,这里表现的行为就是对其它节点的请求无响应。0 是主节点。整个过程大致是如下:

首先,客户端向主节点发起请求,主节点 0 收到客户端请求,会向其它节点发送 pre-prepare 消息,其它节点就收到了pre-prepare 消息,就开始了这个核心三阶段共识过程了。

1. Pre-prepare 阶段:节点收到 pre-prepare 消息后,会有两种选择,一种是接受,一种是不接受。什么时候才不接受主节点发来的 pre-prepare 消息呢?一种典型的情况就是如果一个节点接受到了一条 pre-pre 消息,消息里的 v 和 n 在之前收到里的消息是曾经出现过的,但是 d 和 m 却和之前的消息不一致,或者请求编号不在高低水位之间(高低水位的概念在下文会进行解释),这时候就会拒绝请求。拒绝的逻辑就是主节点不会发送两条具有相同的 v 和 n ,但 d 和 m 却不同的消息。

在PBFT(Practical Byzantine Fault Tolerance)算法中,vndm 是消息中的关键字段,分别代表以下内容:

  1. v(View Number):表示当前视图编号。PBFT 算法通过视图编号来区分不同的主节点(Primary)。每个视图都有一个唯一的主节点,负责协调共识过程。如果主节点出现问题,系统会切换到新的视图,视图编号会递增。
  2. n(Sequence Number):表示请求的序列号。每个客户端请求都会被分配一个唯一的序列号,用于确保请求的顺序性。序列号帮助节点确定请求的处理顺序,并防止重复处理。
  3. d(Digest)或者D(m):表示请求消息的摘要(哈希值)。摘要用于唯一标识请求的内容,确保消息的完整性和一致性。节点可以通过比较摘要来验证消息是否被篡改。
  4. m(Message):表示实际的请求消息内容。这是客户端发送的原始请求,包含了具体的操作或指令。
  5. i:节点的编号

如果节点之前已经收到过具有相同 vn 的消息,但 dm 不同,这意味着主节点可能发送了不一致的消息,或者存在恶意行为。此时,节点会拒绝该消息。

2. Prepare 阶段:节点同意请求后会向其它节点发送 prepare 消息。这里要注意一点,同一时刻不是只有一个节点在进行这个过程,可能有 n 个节点也在进行这个过程。因此节点是有可能收到其它节点发送的 prepare 消息的。在一定时间范围内,如果收到超过 2f 个不同节点的 prepare 消息,就代表 prepare 阶段已经完成。

3. Commit 阶段:于是进入 commit 阶段。向其它节点广播 commit 消息,同理,这个过程可能是有 n 个节点也在进行的。因此可能会收到其它节点发过来的 commit 消息,当收到 2f+1 个 commit 消息后(包括自己),代表大多数节点已经进入 commit 阶段,这一阶段已经达成共识,于是节点就会执行请求,写入数据。

处理完毕后,节点会返回消息给客户端,这就是 pbft 算法的全部流程。为了更清晰的展现 这个过程和一些细节,下面以流程图来表示这个过程:

5. checkpoint 、stable checkpoint和高低水位

Checkpoint 是系统在某个时刻的状态快照。它记录了当前所有已达成共识的请求及其执行结果。检查点的主要作用是减少系统恢复时的开销,因为节点不需要从初始状态重新执行所有请求。 假设系统已经处理了 100 个请求(序列号 1 到 100),节点会生成一个检查点,记录这 100 个请求的执行结果。如果系统在后续运行中崩溃,节点可以从这个检查点恢复,而不需要重新执行前 100 个请求。


那什么是 stable checkpoint (稳定检查点)呢?stable checkpoint 就是大部分节点 (2f+1) 已经共识完成的最大请求序号。 假设系统中有 4 个节点(f = 1,因为 2f + 1 = 3),节点 A、B、C 和 D 都生成了序列号为 100 的检查点。如果至少 3 个节点(例如 A、B、C)确认了这个检查点,那么它就成为稳定检查点。此时,系统可以安全地清理序列号 1 到 100 的日志。


高低水位 是 PBFT 算法中用于限制请求序列号范围的机制。它们确保节点只处理一定范围内的请求,防止恶意节点通过发送大量无效请求耗尽序列号空间。

  • 低水位(Low Watermark):表示系统已经确认的最后一个稳定检查点的序列号。
  • 高水位(High Watermark):表示系统可以接受的最大序列号,通常是低水位加上一个固定的窗口大小(例如 200)。

6. ViewChange(视图更改)事件

当主节点挂了(超时无响应)或者从节点集体认为主节点是问题节点时,就会触发 ViewChange 事件, ViewChange 完成后,视图编号将会加 1 。下图展示 ViewChange 的三个阶段流程:

a. 步骤 1:触发 View-Change 消息

当副本节点认为主节点出现故障时,它们会广播一条 View-Change 消息给其他节点。这条消息包含以下信息:

  • v+1:新的视图编号(当前视图编号加 1)。
  • 最新的稳定检查点:副本节点已经确认的最后一个稳定检查点。
  • P集合:副本节点已经 prepared 但尚未 committed 的请求集合。

b. 步骤 2:收集 View-Change 消息

新的主节点(通常是下一个视图编号对应的节点)会等待收集足够多的 View-Change 消息。具体来说,它需要收到至少 2f + 1View-Change 消息(其中 f 是系统中最多可能存在的恶意节点数)。

c. 步骤 3:广播 New-View 消息

新的主节点在收集到足够多的 View-Change 消息后,会广播一条 New-View 消息给所有副本节点。这条消息包含以下信息:

  • v+1:新的视图编号。
  • V集合:所有收到的 View-Change 消息。
  • Q集合:新的主节点选择的请求集合,用于在新的视图中继续处理。

d. 步骤 4:切换到新视图

副本节点收到 New-View 消息后,会验证消息的合法性(例如检查是否有足够多的 View-Change 消息),然后切换到新的视图。新的主节点开始接收客户端请求,并继续执行共识过程。

引用:

1. PBFT论文

2. https://zhuanlan.zhihu.com/p/35847127

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用Python和Tkinter标准模块建立密码管理器

用Python和Tkinter标准模块建立密码管理器 创建一个简单的密码管理器应用程序&#xff0c;帮助用户存储和管理他们的密码。使用Python的tkinter模块来创建一个图形用户界面&#xff08;GUI&#xff09;。 本程序支持 添加、查看、搜索、复制、修改、删除 功能。 本程序使用 …

OpenAI模块重构

文章目录 1.common-openai-starter1.目录结构2.OpenAiProperties.java 新增apiUrl3.OpenAIAutoConfiguration.java4.OpenAiClient.java 使用gson重构 2.common-openai-starter-demo1.目录结构2.application.yml 新增api-url3.OpenAiController.java4.OpenAiApplication.java5.测…

数据标注开源框架 Label Studio

数据标注开源框架 Label Studio Label Studio 是一个开源的、灵活的数据标注平台&#xff0c;旨在帮助开发者和数据科学家轻松创建高质量的训练数据集。它支持多种类型的数据&#xff08;如文本、图像、音频、视频等&#xff09;以及复杂的标注任务&#xff08;如分类、命名实体…

详解:TCP/IP五层(四层)协议模型

一.五层&#xff08;四层&#xff09;模型 1.概念 TCP/IP协议模型分为五层&#xff1a;物理层、数据链路层、网络层、传输层和应用层。这五层每一层都依赖于其下一层给它提供的网络去实现需求。 1&#xff09;物理层&#xff1a;这是最基本的一层&#xff0c;也是最接近硬件…

使用Python进行大模型的测试与部署

随着人工智能技术的飞速发展&#xff0c;大规模模型在各行各业的应用日益广泛。然而&#xff0c;如何有效测试这些模型以确保其稳定性和准确性&#xff0c;成为测试人员的们面临的一大挑战。本文将详细介绍在Python环境下&#xff0c;如何测试大模型&#xff0c;并探讨其部署策…

高并发处理 --- 超卖问题+一人一单解决方案

在高并发场景下&#xff0c;超卖和一人一单是两个典型的并发问题。为了解决这两个问题&#xff0c;我们可以使用乐观锁&#xff08;CAS&#xff09;和悲观锁&#xff0c;这两者分别有不同的实现方式和适用场景。下面我们详细介绍如何通过 乐观锁&#xff08;CAS&#xff09; 和…

【2024年华为OD机试】(C卷,100分)- 约瑟夫问题 (JavaScriptJava PythonC/C++)

一、问题描述 题目描述 输入一个由随机数组成的数列&#xff08;数列中每个数均是大于 0 的整数&#xff0c;长度已知&#xff09;&#xff0c;和初始计数值 m。 从数列首位置开始计数&#xff0c;计数到 m 后&#xff0c;将数列该位置数值替换计数值 m&#xff0c;并将数列…

浅谈APP之历史股票通过echarts绘图

浅谈APP之历史股票通过echarts绘图 需求描述 今天我们需要做一个简单的历史股票收盘价格通过echarts进行绘图&#xff0c;效果如下&#xff1a; 业务实现 代码框架 代码框架如下&#xff1a; . 依赖包下载 我们通过网站下载自己需要的涉及的图标&#xff0c;勾选之后进…

【0x0012】HCI_Delete_Stored_Link_Key命令详解

目录 一、命令参数 二、命令格式及参数 2.1. HCI_Delete_Stored_Link_Key 命令格式 2.2. BD_ADDR 2.3. Delete_All 三、生成事件及参数 3.1. HCI_Command_Complete事件 3.2. Status 3.3. Num_Keys_Deleted 四、命令执行流程 4.1. 命令发送阶段 4.2. 控制器处理阶段…

提示词的艺术 ---- AI Prompt 进阶(提示词框架)

提示词的艺术 ---- AI Prompt 进阶&#xff08;提示词框架&#xff09; 写在前面 上周发布了一篇《提示词的艺术----AI Prompt撰写指南》&#xff0c;旨在帮助读者理解提示词的作用&#xff0c;以及简单的提示词撰写指南。本篇作为进阶内容&#xff0c;将给出常用的提示词框架…

javaSE.类的继承

在定义不同类的时候,为了方便使用可以将这些共同属性抽象成一个父类,在定义其他子类时可以继承自该父类,减少代码的重复定义,子类可以使用父类中非私有成员. extents 没有可用的无形参构造方法 被构造方法覆盖了 super 需要调用父类的构造方法 super必须是构造主体的第一条语…

统计文本文件中单词频率的 Swift 与 Bash 实现详解

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

qt QUrl详解

1、概述 QUrl是Qt框架中用于处理URL&#xff08;统一资源定位符&#xff09;的类&#xff0c;它提供了构建、解析、编码、解码和处理URL的功能。QUrl支持多种协议&#xff0c;如HTTP、HTTPS、FTP以及文件URL等&#xff0c;并能处理URL的各个组成部分&#xff0c;如协议、主机、…

c++----------------------多态

1.多态 1.1多态的概念 多态(polymorphism)的概念&#xff1a;通俗来说&#xff0c;就是多种形态。多态分为编译时多态(静态多态)和运⾏时多 态(动态多态)&#xff0c;这⾥我们重点讲运⾏时多态&#xff0c;编译时多态(静态多态)和运⾏时多态(动态多态)。编译时 多态(静态多态)…

javaSE.类与对象

类与对象 人类&#xff0c;鸟类&#xff0c;鱼类... 例如人&#xff0c;具有不同性格&#xff0c;但根本上都是人。 对象是某一类事物实际存在的每个个体&#xff08;实例&#xff09;例如&#xff1a;雷军 A:谁拿走了我的手机&#xff1f; B:是个人&#xff08;类&#xff0…

Windows cmd常用命令

文章目录 Windows cmd常用命令一、引言二、文件和目录操作1、查看和切换目录2、文件和目录的创建与删除 三、系统信息与网络配置1、系统信息2、网络配置 四、使用示例五、总结 Windows cmd常用命令 一、引言 Windows 命令提示符&#xff08;cmd&#xff09;是一个强大的工具&a…

保健食品注册数据库<一键查询保健食品信息>

在保健品市场竞争激烈的情况下&#xff0c;企业要如何保障产品合规、信息公开&#xff0c;并且能够迅速应对市场变化呢&#xff1f;查询保健食品注册信息是关键环节。 当下&#xff0c;查询保健食品注册信息主要有两种途径&#xff1a;一是利用国家保健食品注册数据库进行查询…

无所不搜,吾爱制造

吾爱论坛作为众多软件资源爱好者的宝藏之地&#xff0c;汇聚了许多优秀的软件作品&#xff0c;堪称软件界的“福地”。许多技术大佬在这里分享自己的创作。 而今天要介绍的&#xff0c;正是吾爱作者“buyaobushuo”自制的多功能娱乐软件——太极。这款软件基于flet开发&#x…

【C++】详细讲解继承(下)

本篇来继续说说继承。上篇可移步至【C】详细讲解继承&#xff08;上&#xff09; 1.继承与友元 友元关系不能继承 &#xff0c;也就是说基类友元不能访问派⽣类私有和保护成员。 class Student;//前置声明class Same //基类 { public:friend void Fun(const Same& p, con…

【二叉树】4. 判断一颗二叉树是否是平衡二叉树。5. 对称二叉树。6. 二叉树的构建及遍历 7. 二叉树的分层遍历 。

判断一颗二叉树是否是平衡二叉树。OJ链接 可以在求树高度的过程中判断树是否平衡 对称二叉树。OJ链接 二叉树的构建及遍历。OJ链接 注意&#xff1a;public static int i最好把static去掉 否则当有多个测试用例时 i无法重新为0二叉树的分层遍历 。OJ链接 但此题要求返回List…