趣谈拜占庭将军问题

news2024/9/22 13:37:14

拜占庭将军问题(The Byzantine Generals Problem),它其实是借拜占庭将军的故事展现了分布式共识问题,还探讨和论证了解决的办法。而大多数人觉得它难理解,除了因为分布式共识问题比较复杂之外,还与莱斯利·兰伯特(Leslie Lamport)的讲述方式有关,他在一些细节上(比如,口信消息型拜占庭问题之解的算法过程上)没有说清楚。

实际上,它是分布式领域最复杂的一个容错模型,一旦搞懂它,你就能掌握分布式共识问题的解决思路,还能更深刻地理解常用的共识算法,在设计分布式系统的时候,也能根据场景特点选择适合的算法,或者设计适合的算法了。而我把拜占庭将军的问题放到第一讲,主要是因为它很好地抽象了分布式系统面临的共识问题,理解了这个问题,会为你接下来的学习打下基础。

那么接下来,我就以战国时期六国抗秦的故事为主线串联起整篇文章,让你读懂、学透。

苏秦的困境

战国时期,齐、楚、燕、韩、赵、魏、秦七雄并立,后来秦国的势力不断强大起来,成了东方六国的共同威胁。于是,这六个国家决定联合,全力抗秦,免得被秦国各个击破。一天,苏秦作为合纵长,挂六国相印,带着六国的军队叩关函谷,驻军在了秦国边境,为围攻秦国作准备。但是,因为各国军队分别驻扎在秦国边境的不同地方,所以军队之间只能通过信使互相联系,这时,苏秦面临了一个很严峻的问题:如何统一大家的作战计划?

万一一些诸侯国在暗通秦国,发送误导性的作战信息,怎么办?如果信使被敌人截杀,甚至被敌人间谍替换,又该怎么办?这些都会导致自己的作战计划被扰乱,然后出现有的诸侯国在进攻,有的诸侯国在撤退的情况,而这时,秦国一定会趁机出兵,把他们逐一击破的。

所以,如何达成共识,制定统一的作战计划呢?苏秦他很愁。

这个故事,是拜占庭将军问题的一个简化表述,苏秦面临的就是典型的共识难题,也就是如何在可能有误导信息的情况下,采用合适的通讯机制,让多个将军达成共识,制定一致性的作战计划?

你可以先停下来想想,这个问题难在哪儿?我们又是否有办法,帮助诸侯国们达成共识呢?

二忠一叛的难题

为了便于你理解和层层深入,我先假设只有3个国家要攻打秦国,这三个国家的三位将军,咱们简单点儿,分别叫齐、楚、燕。同时,又因为秦国很强大,所以只有半数以上的将军参与进攻,才能击败敌人(注意,这里是假设哈,你别较真),在这个期间,将军们彼此之间需要通过信使传递消息,然后协商一致之后,才能在同一时间点发动进攻。

举个例子,有一天,这三位将军各自一脸严肃地讨论明天是进攻还是撤退,并让信使传递信息,按照“少数服从多数”的原则投票表决,两个人意见一致就可以了,比如:

  1. 齐根据侦查情况决定撤退;
  2. 楚和燕根据侦查信息,决定进攻。

那么按照原则,齐也会进攻。最终,3支军队同时进攻,大败秦军。

alt

可是,问题来了: 一旦有人在暗通秦国,就会出现作战计划不一致的情况。比如齐向楚、燕分别发送了“撤退”的消息,燕向齐和楚发送了“进攻”的消息。 撤退:进攻=1:1,无论楚投进攻还是撤退,都会成为2:1,这个时候还是会形成一个一致性的作战方案。

但是,楚这个叛徒在暗中配合秦国,让信使向齐发送了“撤退”,向燕发送了“进攻”,那么:

  • 燕看到的是,撤退:进攻=1:2;
  • 齐看到的是,撤退:进攻=2:1。

按照“少数服从多数”的原则,就会出现燕单独进攻秦军,当然,最后肯定是因为寡不敌众,被秦军给灭了。

alt

在这里,你可以看到,叛将楚通过发送误导信息,非常轻松地干扰了齐和燕的作战计划,导致这两位忠诚将军被秦军逐一击败。 这就是所说的二忠一叛难题。 那么苏秦应该怎么解决这个问题呢?我们来帮苏秦出出主意。

如果你觉得上面的逻辑有点绕的话,可以找张白纸,自己比划比划。

苏秦该怎么办?

解决办法一:口信消息型拜占庭问题之解

先来说说第一个解决办法。首先,三位将军都分拨一部分军队,由苏秦率领,苏秦参与作战计划讨论并执行作战指令。这样,3位将军的作战讨论,就变为了4位将军的作战讨论,这能够增加讨论中忠诚将军的数量。

然后呢,4位将军还约定了,如果没有收到命令,就执行预设的默认命令,比如“撤退”。除此之外,还约定一些流程来发送作战信息、执行作战指令,比如,进行两轮作战信息协商。为什么要执行两轮呢?先卖个关子,你一会儿就知道了。

第一轮:

  • 先发送作战信息的将军作为指挥官,其他的将军作为副官;
  • 指挥官将他的作战信息发送给每位副官;
  • 每位副官,将从指挥官处收到的作战信息,作为他的作战指令;如果没有收到作战信息,将把默认的“撤退”作为作战指令。

第二轮:

  • 除了第一轮的指挥官外,剩余的3位将军将分别作为指挥官,向另外2位将军发送作战信息;
  • 然后,这3位将军按照“少数服从多数”,执行收到的作战指令。

为了帮助你直观地理解苏秦的整个解决方案,我来演示一下作战信息协商过程。 而且,我会分别以忠诚将军和叛将先发送作战信息为例来演示, 这样可以完整地演示叛将对作战计划干扰破坏的可能性。

首先是3位忠诚的将军先发送作战信息的情况。

为了演示方便,假设苏秦先发起作战信息,作战指令是“进攻”。那么在第一轮作战信息协商中,苏秦向齐、楚、燕发送作战指令“进攻”。

alt

在第二轮作战信息协商中,齐、楚、燕分别作为指挥官,向另外2位发送作战信息“进攻”,因为楚已经叛变了,所以,为了干扰作战计划,他就对着干,发送“撤退”作战指令。

alt

最终,齐和燕收到的作战信息都是“进攻、进攻、撤退”,按照原则,齐和燕与苏秦一起执行作战指令“进攻”,实现了作战计划的一致性,保证了作战的胜利。

那么,如果是叛徒楚先发送作战信息,干扰作战计划,结果会有所不同么?我们来具体看一看。在第一轮作战信息协商中,楚向苏秦发送作战指令“进攻”,向齐、燕发送作战指令“撤退”。

alt

然后,在第二轮作战信息协商中,苏秦、齐、燕分别作为指挥官,向另外两位发送作战信息。

alt

最终,苏秦、齐和燕收到的作战信息都是“撤退、撤退、进攻”,按照原则,苏秦、齐和燕一起执行作战指令“撤退”,实现了作战计划的一致性。也就是说,无论叛将楚如何捣乱,苏秦、齐和燕,都执行一致的作战计划,保证作战的胜利。

这个解决办法,其实是兰伯特在论文《 The Byzantine Generals Problem》中提到的口信消息型拜占庭问题之解: 如果叛将人数为m,将军人数不能少于3m + 1 ,那么拜占庭将军问题就能解决了。 不过,作者在论文中没有讲清楚一些细节,为了帮助你阅读和理解论文,在这里我补充一点:

这个算法有个前提,也就是叛将人数m,或者说能容忍的叛将数m,是已知的。在这个算法中,叛将数m决定递归循环的次数(也就是说,叛将数m决定将军们要进行多少轮作战信息协商),即m+1轮(所以,你看,只有楚是叛变的,那么就进行了两轮)。你也可以从另外一个角度理解:n位将军,最多能容忍(n - 1) / 3位叛将。 关于这个公式,你只需要记住就好了,推导过程你可以参考论文。

不过,这个算法虽然能解决拜占庭将军问题,但它有一个限制:如果叛将人数为m,那么将军总人数必须不小于3m + 1。

在二忠一叛的问题中,在存在1位叛将的情况下,必须增加1位将军,将3位将军协商共识,转换为4位将军协商共识,这样才能实现忠诚将军的一致性作战计划。那么有没有办法,在不增加将军人数的时候,直接解决二忠一叛的难题呢?

解决办法二:签名消息型拜占庭问题之解

其实,苏秦还可以通过签名的方式,在不增加将军人数的情况下,解决二忠一叛的难题。首先,苏秦要通过印章、虎符等信物,实现这样几个特性:

  • 忠诚将军的签名无法伪造,而且对他签名消息的内容进行任何更改都会被发现;
  • 任何人都能验证将军签名的真伪。

这时,如果忠诚的将军,比如齐先发起作战信息协商,一旦叛将小楚修改或伪造收到的作战信息,那么燕在接收到楚的作战信息的时候,会发现齐的作战信息被修改,楚已叛变,这时他将忽略来自楚的作战信息,最终执行齐发送的作战信息。

alt

如果叛变将军楚先发送误导的作战信息,那么,齐和燕将按照一定规则(比如取中间的指令)在排序后的所有已接收到的指令中(比如撤退、进攻)中选取一个指令,进行执行,最终执行一致的作战计划。

alt

这个解决办法,是兰伯特在论文中提到的签名消息型拜占庭问题之解。而通过签名机制约束叛将的叛变行为,任何叛变行为都会被发现,也就会实现无论有多少忠诚的将军和多少叛将,忠诚的将军们总能达成一致的作战计划。

我想,如果当时苏秦能够具备分布式系统设计的思维,掌握这几种算法,应该就不用担心作战计划被干扰了吧。

总结

本文讲述了苏秦协商作战的故事,现在让我们跳回现实世界,回到计算机世界的分布式场景中:

  • 故事里的各位将军,你可以理解为计算机节点;
  • 忠诚的将军,你可以理解为正常运行的计算机节点;
  • 叛变的将军,你可以理解为出现故障并会发送误导信息的计算机节点;
  • 信使被杀,可以理解为通讯故障、信息丢失;
  • 信使被间谍替换,可以理解为通讯被中间人攻击,攻击者在恶意伪造信息和劫持通讯。

这样一来,你是不是就理解了计算机分布式场景中面临的问题,并且知道了解决的办法呢?

那么我想强调的是,拜占庭将军问题描述的是最困难的,也是最复杂的一种分布式故障场景,除了存在故障行为,还存在恶意行为的一个场景。你要注意,在存在恶意节点行为的场景中(比如在数字货币的区块链技术中),必须使用拜占庭容错算法(Byzantine Fault Tolerance,BFT)。除了故事中提到两种算法,常用的拜占庭容错算法还有:PBFT算法,PoW算法。

而在计算机分布式系统中,最常用的是非拜占庭容错算法,即故障容错算法(Crash Fault Tolerance,CFT)。 CFT解决的是分布式的系统中存在故障,但不存在恶意节点的场景下的共识问题。 也就是说,这个场景可能会丢失消息,或者有消息重复,但不存在错误消息,或者伪造消息的情况。常见的算法有Paxos算法、Raft算法、ZAB协议(这些内容我同样会在后面讲解)。

那么,如何在实际场景选择合适的算法类型呢?答案是:如果能确定该环境中各节点是可信赖的,不存在篡改消息或者伪造消息等恶意行为(例如DevOps环境中的分布式路由寻址系统),推荐使用非拜占庭容错算法;反之,推荐使用拜占庭容错算法,例如在区块链中使用PoW算法。

本文由 mdnice 多平台发布

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

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

相关文章

【C++ OJ练习】6.验证回文串

1.题目链接 力扣 2.解题思路 字母全部要变成小写 并且不能管空格和标点 这样从前和后分别遍历并进行比较 如果遇到不是相同 字符的话 说明不是回文串 就这样一直往下走 直到最后两下标相遇 那么就是回文串 注意双循环条件 3.代码 class Solution { public://除去标点和空…

【如何在深度学习的道路上越走越远?——《深度学习模式与实践》】

作为近几年人工智能领域的主要研究方向之一,深度学习主要通过构建深度卷积神经网络和采用大量样本数据作为输入,最终得到一个具有强大分析能力和识别能力的模型。深度学习可以是有监督的、半监督的或无监督的。深度学习架构(例如深度神经网络、深度信念网…

Docker查看相关存储信息以及扩容

Docker查看相关存储信息以及扩容 (mac环境) 查看docker基本信息: docker info可以看到docker的存储位置在这里 2. 查看mac的所有盘以及分区大小情况 diskutil listdocker查看网络信息: docker ps # 查看所有在运行的container信…

Zabbix——监控模板

方法二:自定义监控模板 案例:自定义监控客户端服务器登录的人数 需求:监控客户端的登录人数,超过 3 个就发出报警信息 1)在客户端创建自定义 key #在客户端创建自定义 key1.明确需要执行的 linux 命令who | wc -l​…

分类分级一小步,数据安全一大步

启明星辰集团凭借自身在数据安全治理管控的技术优势及各类数据安全治理项目的经验积累,以数据安全治理管控平台(DSMP)为基础,定制研发出数据分类分级系统,它是一款面向数据对象,可实现数据自动化分类分级的…

计算机视觉中的感受野

一、感受野的定义 感受野( R e c e p t i v e Receptive Receptive F i e l d Field Field)的定义是卷积神经网络每一层输出的特征图( f e a t u r e feature feature m a p map map)上的像素点在原始输入图片上映射的区域大小…

4.10 x64dbg 反汇编功能的封装

LyScript 插件提供的反汇编系列函数虽然能够实现基本的反汇编功能,但在实际使用中,可能会遇到一些更为复杂的需求,此时就需要根据自身需要进行二次开发,以实现更加高级的功能。本章将继续深入探索反汇编功能,并将介绍如…

redis缓存简介

1、为什么使用redis 分析:博主觉得在项目中使用redis,主要是从两个角度去考虑:性能和并发。当然,redis还具备可以做分布式锁等其他功能,但是如果只是为了分布式锁这些其他功能,完全还有其他中间件(如zookpeer等)代替,并…

中国地图数据可视化制作,python的pyecharts模块读取excel可视化,

数据格式如下: import pandas as pd from pyecharts import options as opts from pyecharts.charts import Map from pyecharts.globals import ChartType# 读取Excel数据 data pd.read_excel(C:\\Users\\Administrator\\Desktop\\国内数据.xlsx)# 创建地图实例 m…

C语言itoa转化为二进制

C语言itoa函数常常用于把整型转换为字符数组;最常用的是十进制的转换; 也可以用于获取一个数的二进制; 在C语言中 3&51;&是按位与; 先输出3&5; 再分别输出3和5的二进制看一下; …

Shader 基础之 Unity Shader概念

目录 目录 Shader compilation Conditionals in shaders Different types of conditionals Switch code branch at runtime Branching in shaders Static branching How to use static branching Dynamic branching How to use dynamic branching Shader variants …

选读SQL经典实例笔记04_日期运算(上)

1. 年月日加减法 1.1. DB2 1.1.1. sql select hiredate -5 day as hd_minus_5D,hiredate 5 day as hd_plus_5D,hiredate -5 month as hd_minus_5M,hiredate 5 month as hd_plus_5M,hiredate -5 year as hd_minus_5Y,hiredate 5 year as hd_plus_5Yfrom empwhere dept…

【计算机网络】第三章 数据链路层(虚拟机与局域网)

文章目录 3.9 以太网交换机自学习和转发桢的流程3.10 以太网交换机的生成树协议STP3.11 虚拟局域网3.11.1 虚拟局域网VLAN概述3.11.2 虚拟局域网VLAN的实现机制 3.9 以太网交换机自学习和转发桢的流程 以太网交换机的自学习和转发数据帧的流程如下: 自学习&#x…

Mac中使用命令行来加密压缩zip文档

背景 最近需要对一些文件加密,但是Mac上没有找到相应的加密工具,macOS中创建密码保护的压缩 zip 文件很容易并且不需要任何额外附加物或下载。使用命令行的方式处理即可。对压缩包加密之后便意味着有人想要解压缩zip文件时,必须输入正确的密码…

Layui入门必看:登录注册界面搭建与功能开发解析

目录 Layui介绍 什么是Layui? Layui入门 Layui登录实例 导入jar 配置 导入Layui 编写公共jsp 编写代码 Layui注册实例 代码实例 Layui介绍 Layui是一款面向前端开发者的轻量级JavaScript库,旨在简化网页开发过程。它提供了丰富的基础UI组件和…

电气设备漏电保护方式研究

摘要:电气设备漏电故障可能对无防范意识人员产生触电危害,轻者灼伤人体接触位置,重者危及人员生命,甚至会产生漏电火花引起火灾,给企业带来不可估计的损失。文中浅谈电气设备漏电危害性及漏电保护方式,意指…

C++使用rapidjson读写json数据

一、背景 RapidJSON简介及使用_fengbingchun的博客-CSDN博客 rapidjson是腾讯的高效C Json解析器,只有头文件,可跨平台使用 mirrors / Tencent / rapidjson GitCode 二、读数据 使用rapidjson解析和组装json_youyicc的博客-CSDN博客 三、写数据 …

AES加解密算法强化训练

目标: 使用openssl算一遍,再使用网页在线工具算一遍,看看结果是否一样 构造数据 如何编写一个二进制规律性的文件, 比如你可以编写一个"0123456789abcdef"的文本文件,记得删除换行符 然后用ultraedit打开,…

常见加密算法介绍

文章目录 一、背景:二、几种常见的加密算法1. 不可逆加密算法(哈希算法):1.1 MD51.1.1 优点:1.1.2 缺点:1.1.3 Demo:1.1.4 案例分析: 1.2 SHA-2561.2.1 Demo:1.2.2 案例分…

day19三数之和 int *returnSize,int ** returnColumnSizes的理解

题目描述 *1.关于参数 int returnSize, int ** returnColumnSizes的理解 具体看这篇文章 [https://blog.csdn.net/m0_52775920/article/details/121461911?spm1001.2014.3001.5502] (1)*returnSize 的理解 returnSize 返回大小为returnSize的二维数组&…