白话讲解,拜占庭将军问题

简介: 作为服务端开发的同学,你可能听说过Paxos、Raft这类分布式一致性算法,也在工作中使用过ZooKeeper、etcd等工具来解决一致性问题。但你可能不知道,这些算法和工具解决的并不是一致性中最难的问题,要讨论这个最难的问题,这就要追溯到 Leslie Lamport 1982 年发表的著名论文 《拜占庭将军问题》(The Byzantine Generals Problem )上了。

作为服务端开发的同学,你可能听说过Paxos、Raft这类分布式一致性算法,也在工作中使用过ZooKeeper、etcd等工具来解决一致性问题。但你可能不知道,这些算法和工具解决的并不是一致性中最难的问题,要讨论这个最难的问题,这就要追溯到 Leslie Lamport 1982 年发表的著名论文 《拜占庭将军问题》(The Byzantine Generals Problem )上了。


微信图片_20220608211110.jpg


1、拜占庭将军问题是什么?


拜占庭将军问题,其实是一个共识问题。通过比喻的方式来描述分布式一致性中一类最难的问题,这里大致叙述一下:


拜占庭帝国派出多支军队去围攻一个强大的敌人,每支军队有一个将军,但由于彼此距离较远,他们之间只能通过信使传递消息。敌方很强大,必须有超过半数的拜占庭军队一同参与进攻才可能击败敌人。在此期间,将军们彼此之间需要通过信使传递消息并协商一致后,在同一时间点发动进攻。


问题难点:困扰这些将军的问题,是他们不确定他们中是否有叛徒,叛徒可能会擅自变更进攻意向或者进攻时间。在这种状态下,拜占庭的将军们能否找到一种分布式的协议来让他们能够远程协商,从而赢取战斗?


以上,这就是著名的拜占庭将军问题。


2、问题实质推演


回顾上述问题:


一群将军想要实现某一个目标(一致进攻或者一致撤退),但是单独行动行不通,必须合作, 达成共识;由于叛徒的存在,将军们不知道应该如何达到一致。


注意,这里“一致性”才是拜占庭将军问题探讨的内容,如果本来叛徒数量就已经多到了问题不可解的地步,这个就是“反叛”的问题了;同时,我们的目标是忠诚的将军能够达成一致,对于这些忠诚的将军来说,进攻或者撤退都是可以的,只要他们能够达成一致就行。


但是,仔细想想:光靠“一致性”就可以解决问题吗?


考虑一下,如果万事俱备,客观上每个忠诚的将军只要进攻了就一定能够胜利,但是却因为叛徒的存在他们都“一致性”没有进攻;反之,条件不利,将军们不应该进攻,但是却因为叛徒的存在所有人都“一致性”进攻了。所以,我们还需要提出一个“正确性”要求。


那我们该如何定义这个“正确性”呢?


我们或许可以简单地说,正确就是每个忠诚的将军都正确的表达了自己的意思,不会因为叛徒让别的将军认为忠诚的将军是叛徒而不采用他传达的消息。最终,所有忠诚的将军都能够让别的将军接收到自己的真实意图,并最终一致行动;而形式化的要求就是:“一致性”与“正确性”


3、难题细化分析


介绍到现在,想必大家还是比较疑惑,我们以具体案例辅助解释一下:


我们把问题简化一下,假设只有三个拜占庭将军,分别为A、B、C,他们要决定的只有一件事情:明天是进攻还是撤退。为此,将军们需要依据“少数服从多数”原则投票表决,只要有两个人意见达成一致就可以了。


举例来说,A和B投进攻,C投撤退:


  • 那么A的信使传递给B和C的消息都是进攻


  • B的信使传递给A和C的消息都是进攻


  • 而C的信使传给A和B的消息都是撤退


如此一来,三个将军就都知道进攻方和撤退方二者占比是 2 : 1 了。显而易见,进攻方胜出,第二天大家都要进攻,三者行动最终达成一致。


目前看来一切比较顺利,理解起来也非常简单。但是,假如三个将军中存在了一个叛徒呢?

叛徒的目的是破坏忠诚将军间一致性的达成,让拜占庭的军队遭受损失。


3.1 问题难点


假设A和B是忠诚将军,A投进攻,B投撤退,如果C是这个叛徒将军,那么C该做些什么,才能在第二天让两个忠诚的将军做出相反的决定呢?


目前看来,进攻方和撤退方现在是 1 : 1 ,无论C投哪一方,都会变成 2 : 1 ,一致性还是会达成。但是,作为叛徒的C,你必然不会按照常规出牌,于是你让一个信使告诉A的内容是你“要进攻”,让另一个信使告诉B的则是你“要撤退”。


至此,A将军看到的投票结果是:


进攻方 :撤退方 = 2 : 1


而B将军看到的投票结果是:


进攻方 :撤退方 = 1 : 2


第二天,忠诚的A冲上了战场,却发现只有自己一支军队发起了进攻,而同样忠诚的B,却早已撤退。最终,A的军队败给了敌人。


截止目前,你有没有发现,明明大多数将军都是忠诚的(2/3),却被少数的叛徒(1/3)耍得团团转?


实质上,“拜占庭将军”问题的可怕之处,恰恰在此:在一致性达成的过程中,叛徒将军(恶意节点)甚至不需要超过半数,就可以破坏占据多数的正常节点一致性的达成。


3.2 狡猾的叛徒


这时候,会存在你可能不相信甚至无法接受的一种情况:在大多数将军都是忠诚的情况下,却无法抓出这个为所欲为的叛徒。


还是上面的例子,假设A与B是忠诚的将军,C是叛徒将军。忠诚的将军经历了上次战役的失败,就已经发觉他们中出现了叛徒,但是并不知道具体是谁。


依旧是上面投票的例子,A投进攻,B投撤退,C传递给A和B两种不同的消息。


现在,我们从忠诚将军A的视角来看一下,他是如何做决策的。


A现在知道另外两人中可能有一个是叛徒,他收到了B的撤退消息和C的进攻消息,他应该如何分辨呢?


A可以问一下B:“我从C那儿收到的是进攻,你从C那儿收到的是什么?”


因为B是忠诚的将军,不会伪造信息,B会告诉A:“收到的是撤退。”


C发送了两条不同的消息,A现在也发现了这个问题,但是A现在就可以判断C是叛徒了么?


可悲的事情发生了,尽管忠诚的B说了实话,但是A反而对他产生了怀疑。因为从A的视角来看,B和C的说法不一致,他无法判断:


  • 到底是第一次发送了两条不同消息的C是叛徒呢?


  • 还是明明C初次告知了B的是进攻,B却和A说C告知的是撤退,B是叛徒呢?


同样的情况,也会出现在B身上,两个忠诚的将军无法做正确的判断,而可以任意进行信息造假的叛徒C,此时只需要再次进行消息伪造:和A说“B告知我的消息是进攻”,和B说“A告知我的消息是撤退”,如此一来,就可以进一步把信息搞混,从而隐藏了自己是叛徒的真相。


微信图片_20220608211112.png


综上所述,我们可以得出一个结论:在拜占庭三个将军中出现一个叛徒,并且叛徒可以任意伪造消息的情况下,只要叛徒头脑清醒,他就始终无法被发现,甚至还能造成整个系统的信任危机。


根据这一结论进一步推导可以得出一个更通用的结论,如果存在 m 个叛徒将军,那么当将军总数小于或等于 3m 时(n <= 3m,m代表叛徒将军个数),叛徒便无法被发现,整个系统的一致性也就无法达成。


3.3 叛徒是否可被抓?


从上面的结论,可以看出,忠诚将军的人数是叛徒人数 2 倍的时候,依然不能找出叛徒,那么再多一个忠诚的将军呢?


为了简化问题,接下来假设有 4 个拜占庭将军,分别是A、B、C、D,其中有一个是叛徒。我们依然秉承找出叛徒的关键,即判断哪个将军发送了不一致的消息。


也就是说,接下来就是和其他接收到消息的将军进行信息的同步判断:是否收到的消息不一致。


现在,将问题再进一步简化,暂不需要考虑整个投票的过程,只需要考虑一个将军向其他三个将军各发送了一条命令,忠诚将军能否对这个命令达成一致的情况,为了区分发送命令的将将军和接收消息的将军,我们将发送命令的将军称为发令将军(M),将接收命令的将军称为副官(S)。


微信图片_20220608211115.png


考虑下面两个问题:


  • 那么剩下的三个副官能不能通过相互间的信息同步找到叛徒?


  • 或者所有忠臣间达成一致,不让叛徒的分裂想法得逞呢?


这时候就出现了两种情况:


  • 发令将军是叛徒 ;


  • 副官里有叛徒。


Case1:发令将军是叛徒


假设D是叛徒,向A和B发送了进攻,向C发送了撤退。现在,我们切入到A的视角


A问B和C:“我从D那里收到的消息是进攻,你从D那里收到的是什么呢?”


B说是进攻,C说是撤退。


此时,从A的视角来看,C和D对同一条消息的说法是不一致的,那么他们两个人中肯定有一个是叛徒,但是A无法判断的是:


  • D给不同人发送了不一致的消息;


  • 还是C伪造了D的消息。


好在,由于A知道最多只有一个叛徒存在。


那么根据反证法,如果B也是叛徒,就有两个叛徒存在,那么B肯定不是叛徒。


那么A和B至少在D发送的是进攻这一消息上,达成了一致,两者选择都是进攻。


B也是同样的情况,现在A和B彼此建立了信任,而同样是忠诚副官的C,最终则和真正的叛徒D被一同怀疑。


微信图片_20220608211118.png


Case2:副官里有叛徒


假设C是叛徒,D给三个副官都发送了进攻,那么叛徒C应该怎样同步D的消息,才能分裂忠诚的发令将军和忠诚副官间的关系呢?


如果将D的消息原样转发出去,那么这一想法实施后也就无法再去当叛徒了。如果给A与B均发送和D相反的撤退消息,那么就回到了前文所讲的第一种情况,A和B认为D发送的是进攻,发送消息的D也认为自己发送的消息是进攻,忠臣们行动上又一次达成了一致。


然而,为了给系统增加更多的混乱,叛徒C决定再次发送不一致的消息,告诉B自己从D收到的是进攻,告诉A自己从D收到的是撤退。这种情况下,B看到所有人都认为D是进攻,会傻傻地认为大家是个团结一致的集体,没有叛徒。而A会发现C和D中出现了一个叛徒,不过A也再次可以确认B是自己人。此时,A决定再和B同步一轮消息,看看C是不是说了两个不一致的消息,这种情况下,叛徒C就完全暴露了。


微信图片_20220608211120.png


由此可见,在多了一个忠臣的情况下,叛徒需要处处小心,才能避免被发现。与此同时,忠臣们即便在存在混乱信息的情况下,行动上也依旧达成了一致。根据推理,我们可以推导出一个结论:当忠臣的个数为 2m + 1 时,他们可以容忍 m 个叛徒产生的破坏。


总结


至此,拜占庭将军问题的白话解析版本就讲完了。你应该已经知道了 m 个可以任意伪造消息的叛徒能够破坏规模最大为 3m 个将军的一致性。你也已经了解了叛徒是如何通过发送不一致的消息来制造混乱,以及忠诚将军又如何通过交换信息在混乱中保持一致的。那么接下来让我们跳出拜占庭将军的比喻回到计算机的世界中。如果三个节点中有一个异常节点,那么最坏情况下两个正常节点之间是无法保证一致性的。


参考文章:https://zhuanlan.zhihu.com/p/65800882


微信图片_20220608211123.jpg


延伸点


“拜占庭将军问题”可以进一步延伸到各个领域。人们在互联网上进行数据交易的时候,总会习惯性依赖强大的第三方平台来进行信任担保。然而,这些解决人们信任问题的第三方正在逐渐失效,因为总有黑客能够抓住第三方平台的漏洞进行金融诈骗。“拜占庭将军问题”中的“叛徒”就是互联网金融交易中的“骗子”,如果第三方平台出现了大漏洞或者为了规避过多的步骤将第三方信任机构撤走,“叛徒”就会利用信息在没有第三方信任机构的担保之下进行“行骗”。在不去花费大量时间、资源揪出这个“叛徒”的情况下,能够让交易者双方都彼此信任、进行正常交易的方式就是区块链。

相关文章
|
6月前
|
存储 算法
摩尔投票的原理详解
摩尔投票的原理详解
153 1
|
6月前
|
算法
将军莫虑,且看此图算法实现
将军莫虑,且看此图算法实现
|
5月前
|
算法 安全 区块链
【区块链】解码拜占庭将军问题:区块链共识机制的哲学基石
拜占庭将军问题,一个由Leslie Lamport于1982年提出的经典分布式系统理论问题,是现代加密货币与区块链技术背后的哲学基础。这一理论模型不仅深刻地影响了计算机科学领域,还成为了构建去中心化信任体系的关键灵感来源。本文将深入剖析拜占庭将军问题的本质、解决方案及其对区块链共识机制的深远影响,为读者揭示这一抽象理论的现实应用价值。
219 0
|
6月前
|
算法
算法人生(3):从“贪心算法”看“战胜拖延”(完美主义版)
本文探讨了拖延症的一个常见原因——完美主义,并从贪心算法的角度提供启示。贪心算法通过局部最优决策逼近全局最优解,不保证全局最优,但寻求满意解。完美主义者的拖延源于高标准、过度关注细节、压力和时间管理困难。为解决这个问题,建议接受不完美,设定合理目标,追求良好效果,以及培养时间管理技巧。通过实例说明,调整心态和策略,可以提高工作效率并克服拖延。
|
算法 程序员
【算法集训专题攻克篇】第二十篇之二叉搜索树
【算法集训专题攻克篇】第二十篇之二叉搜索树
【算法集训专题攻克篇】第二十篇之二叉搜索树
|
存储 域名解析 缓存
计算机网络连环炮40问
计算机网络体系大致分为三种,OSI七层模型、TCP/IP四层模型和五层模型。一般面试的时候考察比较多的是五层模型。
341 0
|
算法 分布式数据库 区块链
再学一道算法题: 食物链(带权并查集)
再学一道算法题: 食物链(带权并查集)
再学一道算法题: 食物链(带权并查集)
|
数据安全/隐私保护
【杂(瞎)谈(聊)】易经当中的密码学
看到这个标题,估计可能会有不少读者会有疑问,易经这不是个文学作品吗,怎么和数学相关的密码学给搞到一起了,这不是标题党蛤, 下面小Q来给大家聊聊在易经当中所体现的一些密码学的思想,有些资料来源也不太确定,我凭借记忆进行搜索的,如有错误还请各位读者海涵。
【杂(瞎)谈(聊)】易经当中的密码学
|
存储 算法 安全
【密码学】杂(瞎)谈(聊)哈希函数
本文依然是闲聊,不讲具体的算法内容,来一个小总结,相信大家看过我写过的文章之后,应该对于md系列算法 sha系列算法 sm3等哈希函数比较熟悉了,不熟悉的读者,我再来安利一下我之前写过的文章或者大家也可以去查阅相关的资料,在这里不再重复描述算法的具体内容了,本文呢,针对哈希函数来一个小小的总结,来看一下哈希函数有哪些公共的特性。
【密码学】杂(瞎)谈(聊)哈希函数
下一篇
无影云桌面