Skip to content

Commit

Permalink
完成拜占庭内容
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Nov 2, 2023
1 parent 36c8b5f commit f1a5938
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 12 deletions.
2 changes: 1 addition & 1 deletion architecture/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

如果 5 年前笔者讲 Serverless(无服务器架构),读者朋友们一定会认为我是个大忽悠,又再造虚无缥缈的概念。可是,质疑阻挡不了技术推陈出新,对于脚步慢的企业/个人,新技术往往从最开始的“看不见”,到后来“看不起”,再到“看不懂”,最后终于“跟不上”。笔者并不是在危言耸听,云计算尽管有许多优势,但也充满了陷阱、歧义和谬误,君不见现在网络中也充斥着下云、ServiceMesh 没吊用的言论?

吴军老师在 《浪潮之巅》中讲”无数企业终究会因为无法跟上时代的步伐,熬不过考验而黯然消逝或者落幕,同时又有无数企业因为踏准了新时代的节奏,立于浪潮之巅“,在当今整个社会迈向数字化转型的背景下,笔者粗浅地下个定义 ”云原生就是新数字时代的节奏“。
吴军老师在 《浪潮之巅》中讲”无数企业终究会因为无法跟上时代的步伐,熬不过考验而黯然消逝或者落幕,同时又有无数企业因为踏准了新时代的节奏,立于浪潮之巅“,在当今整个社会迈向数字化转型的背景下,笔者粗浅地下个定义 ”云原生就是新时代的节奏“。

云原生技术的变革,一定是思想先行。在本章,我们先充分了解云原生出现的背景、目标以及云原生应用技术代表,如图 1-1 所示。了解这些内容之后,在后续章节我们逐渐开始云原生架构实践之旅。

Expand Down
1 change: 1 addition & 0 deletions assets/byzantine-2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions assets/byzantine-3.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions assets/byzantine-4.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions assets/byzantine-5.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions assets/byzantine-6.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
94 changes: 83 additions & 11 deletions consensus/The-Byzantine-General-Problem.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,107 @@ Lamport 认为“故事让问题变得欢迎”,因此他在提出观点和问

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

举例来说,A、B 投票进攻,C 投票撤退:
如图所示,举例来说,A、B 投票进攻,C 投票撤退:

- 那么 A 的信使传递给 B 和 C 的消息都是进攻。
- B 的信使传递给 A 和 C 的消息都是进攻。
- C 信使传递给 A 和 B 的消息都是撤退。

如此一来,三个将军就都知道进攻方和撤退方二者的占比是 2:1 了,显而易见,进攻方胜出,按照少数服从多数原则,C 也会进攻,最终三位将军同时进攻,战争获得胜利。

<div align="center">
<img src="../assets/byzantine-1.svg" width = "300" align=center />
<p>将军 A、B 决定进攻,将军 C 决定撤退</p>
</div>


目前看起来一切比较顺利,理解起来也比较简单,**但假如三位将军中出现一位叛徒呢?** 叛徒的目标是破坏忠诚将军们之间的一致性达成,让拜占庭军队收到损失。比如将军 A 向 将军 B、C 分别发送撤退的消息,将军 B 向将军 A、C 分别发送进攻的消息。如果将军 C 是叛徒,那么 C 该做什么才能让两位忠诚的将军做出相反的决定呢?

目前看来 **撤退:进攻 = 1:1**,无论 C 投哪一方,都会变成 2:1,这时候还是会形成一个一致性的作战方案。可是,作为叛徒,将军 C 肯定不会按常理出牌,于是将军C 让信使告诉将军 A 要进攻,让另一个信使告诉将军 B 要撤退。至此:

- 将军 A 看到的投票结果是 **进攻方:撤退方 = 2:1**
- 将军 B 看到的投票结果是 **进攻方:撤退方 = 1:2**

如图所示,按照少数服从多数的原则,忠诚的将军 A 单独冲向战场,最后的结果当然是将军 A 寡不敌荣,败给了敌人。

<div align="center">
<img src="../assets/byzantine-2.svg" width = "300" align=center />
<p>叛徒向将军 A、B 发送不同的作战指令</p>
</div>


截止目前,同学们是否发现,明明大多数将军都是忠诚的(2/3),却被少数的叛徒(1/3)耍得团团转?实质上,拜占庭将军问题恰恰在此:**在一致性的达成过程中,叛徒将军(恶意节点)甚至不需要超过半数,就可以破坏占据多数正常节点一致性的达成,这也是我们常说的二忠一叛难题**

事实上,你可能不相信甚至无法接受的结论是:对于三个将军中存在一个叛徒的场景,想要总能达到一致的行动方案是不可能的( Lamport 在论文中说的)。此外,论文中给出了一个更加普适的结论:如果存在 m 个叛将,那么至少需要 3m+1个 将军,才能最终达到一致的行动方案。

但是拜占庭问题该怎么解决呢?Lamport 在论文中给出了两种拜占庭将军问题的解决方案,我们先来看第一种。

## 3. 口信消息型解决方案

首先, 对于口信消息(Oral message)的定义如下:

- 任何已经发送的消息都将被正确传达。
- 消息的接收者知道是谁发送了消息。
- 消息的缺席可以被检测。

基于口信消息的定义,我们可以知, 口信消息不能被篡改但是可以被伪造。基于对图场景的推导,我们知道存在一个叛将时,必须再增加 3 个忠将才能达到最终的行动一致。为加深理解,我们将利用 3 个忠将 1 个叛将的场景对口信消息型解决方案进行推导。

在口信消息型解决方案中,首先发送消息的将军称为指挥官,其余将军称为副官。对于 3 忠 1 叛的场景需要进行两轮作战信息协商,如果没有收到作战信息那么默认撤退。

- **第一轮** 指挥官向 3 位副官发送了进攻的消息。
- **第二轮** 三位副官再次进行作战信息协商,由于将军 A、B 为忠将,因此他们根据指挥官的消息向另外两位副官发送了进攻的消息,而将军 C 为叛将,为了扰乱作战计划,他向另外两位副官发送了撤退的消息。最终指挥官、将军 A 和 B 达成了一致的进攻计划,可以取得胜利。

<div align="center">
<img src="../assets/byzantine-3.svg" width = "600" align=center />
<p>指挥官为忠将的场景</p>
</div>

图是指挥官为叛将的场景,在第一轮作战信息协商中,指挥官向将军 A、B 发送了撤退的消息,但是为了扰乱将军 C 的决定向其发送了进攻的消息。在第二轮中,由于所有副官均为忠将,因此都将来自指挥官的消息正确地发送给其余两位副官。最终所有忠将都能达成一致撤退的计划。

<div align="center">
<img src="../assets/byzantine-1.svg" width = "400" align=center />
<img src="../assets/byzantine-4.svg" width = "600" align=center />
<p>指挥官为叛徒的场景</p>
</div>

这个解决方法,其实就是 Lamport 在论文中提到的口信消息型拜占庭将军问题之解(A Solution with Oral Message):**如果叛将人数为 m,将军人数不少于 3m+1,那么最终能达成一致的行动计划**。值的注意的是,在这个算法中,叛将人数 m 是已知的,且叛将人数 m 决定了递归的次数,即叛将数 m 决定了进行作战信息协商的轮数,如果存在 m 个叛将,则需要进行 m+1 轮作战信息协商。这也是上述存在 1 个叛将时需要进行两轮作战信息协商的原因。

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

## 4. 签名消息型解决方案

同样,对签名消息的定义是在口信消息定义的基础上增加了如下两条:

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

基于签名消息的定义,我们可以知道,签名消息无法被伪造或者篡改(关于签名消息,可以看 2.5 节 HTTPS 介绍)。

为了深入理解签名消息型解决方案,我们同样以 3 将军问题为例进行推导。忠将率先发起作战协商的场景,将军 A 率先向将军 B、C 发送了进攻消息,一旦叛将 C 篡改了来自将军 A 的消息,那么将军 B 将发现作战信息被将军 C 篡改,将军 B 将执行将军 A 发送的消息。

<div align="center">
<img src="../assets/byzantine-5.svg" width = "400" align=center />
<p>忠将率先发起作战计划</p>
</div>

按照少数服从多数原则,C 也会进攻,最终三位将军同时进攻,战争获得胜利
图7是叛将率先发起作战协商的场景,叛将General C率先发送了误导的作战信息,那么General A、B将发现General C发送的作战信息不一致,因此判定其为叛将。可对其进行处理后再进行作战信息协商

可是,问题来了:假如三位将军中出现一位叛徒呢?叛徒的目标是破坏忠诚将军们之间的一致性达成,让拜占庭军队收到损失
签名消息型解决方案下,无论叛徒如何捣乱,将军 A、B都能执行一致的作战计划,需要注意,签名消息的拜占庭将军问题之解,也是需要 m+1(m为叛将数量)轮协商。我们也可以从另外一个角度理解:n 位将军,能容忍(n-2)为叛将

最后,签名消息型拜占庭问题之解,解决的是忠将门如何就作战计划达成共识的问题,它不关心现实问题,没有与实际场景结合,比如在合适进攻的时候,忠将们执行的作战计划却是撤退。如果要选择落地的方案,我们可以考虑改进后的拜占庭容错算法,比如 PBFT 算法。

这个解决办法其实就是 Lamport 在论文中提到的口信消息型拜占庭问题之解:如果叛徒人数为 m,将军的人数小于或者等于 3m 时,叛徒便无法被发现,整个系统的一致性也无法解决。
## 5. 拜占庭容错算法与非拜占庭容错算法

看完故事回到现实,分布式系统领域中拜占庭将军问题中的角色与计算机世界的对应关系如下:

- 将军, 对应计算机节点。
- 忠诚的将军, 对应运行良好的计算机节点。
- 叛变的将军, 被非法控制的计算机节点。
- 信使被杀, 通信故障使得消息丢失。
- 信使被间谍替换, 通信被攻击, 攻击者篡改或伪造信息。
- **将军**对应计算机节点。
- **忠诚的将军**对应运行良好的计算机节点。
- **叛变的将军**被非法控制的计算机节点。
- **信使被杀**通信故障使得消息丢失。
- **信使被间谍替换**通信被攻击, 攻击者篡改或伪造信息。

这样一来,你是否理解了分布式场景面临的问题,以及知道了如何解决的办法呢?

拜占庭将军问题描述的是最困难、最复杂的分布式故障场景,该场景除了存在故障行为,还存在恶意行为。存在恶意行为的场景中(比如数字货币、Web3等区块链技术中),我们必须使用拜占庭容错(Byzantine Fault Tolerance)算法。常用的拜占庭容错算法有 PBFT、PoW 算法。
如上文所述,拜占庭将军问题描述的是最困难、最复杂的分布式故障场景,该场景除了存在故障行为,还存在恶意行为。存在恶意行为的场景中(比如数字货币、Web3等区块链技术中),我们必须使用拜占庭容错(Byzantine Fault Tolerance)算法。常用的拜占庭容错算法有 PBFT、PoW 算法。

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

Expand Down

0 comments on commit f1a5938

Please sign in to comment.