diff --git a/.vuepress/config.js b/.vuepress/config.js
index 2566ed29..556b543b 100644
--- a/.vuepress/config.js
+++ b/.vuepress/config.js
@@ -176,15 +176,30 @@ export default defineUserConfig({
'/network/conclusion.md',
]
},
+ {
+ text: '第四章:负载均衡与代理技术',
+ link: '/balance/summary.md',
+ collapsable: false,
+ sidebarDepth: 1,
+ children: [
+ '/balance/balance.md',
+ '/balance/balance-features.md',
+ '/balance/balance-topology.md',
+ '/balance/balance4.md',
+ '/balance/balance7.md',
+ '/balance/global-load-balancer.md',
+ '/balance/conclusion.md',
+ ]
+ },
{
- text: "第四章:数据一致性与分布式事务",
+ text: "第五章:数据一致性与分布式事务",
link: '/distributed-transaction/summary.md',
children: [
'/distributed-transaction/ACID.md',
'/distributed-transaction/CAP.md',
{
- text: "4.3 分布式事务模型",
+ text: "5.3 分布式事务模型",
link: '/distributed-transaction/transaction.md',
children: [
'/distributed-transaction/BASE.md',
@@ -197,7 +212,7 @@ export default defineUserConfig({
]
},
{
- text: '第五章:分布式共识与算法',
+ text: '第六章:分布式共识与算法',
collapsable: true,
link: '/consensus/summary.md',
sidebarDepth: 2,
@@ -205,7 +220,7 @@ export default defineUserConfig({
'/consensus/consensus.md',
'/consensus/Replicated-State-Machine.md',
{
- text: "5.3 Paxos 算法",
+ text: "6.3 Paxos 算法",
link: '/consensus/Paxos.md',
children: [
'/consensus/Paxos-history.md',
@@ -213,7 +228,7 @@ export default defineUserConfig({
]
},
{
- text: "5.4 Raft 算法",
+ text: "6.4 Raft 算法",
link: '/consensus/Raft.md',
children: [
'/consensus/raft-leader-election.md',
@@ -224,22 +239,6 @@ export default defineUserConfig({
'/consensus/conclusion.md',
]
},
- {
- text: '第六章:负载均衡与代理技术',
- link: '/balance/summary.md',
- collapsable: false,
- sidebarDepth: 1,
- children: [
- '/balance/balance.md',
- '/balance/balance-features.md',
- '/balance/balance-topology.md',
- '/balance/balance4.md',
- '/balance/balance7.md',
- '/balance/global-load-balancer.md',
- '/balance/conclusion.md',
- ]
- },
-
{
text: '第七章:容器编排技术',
link: '/container/summary.md',
diff --git a/consensus/Basic-Paxos.md b/consensus/Basic-Paxos.md
index 33da68b8..d7b4b4b6 100644
--- a/consensus/Basic-Paxos.md
+++ b/consensus/Basic-Paxos.md
@@ -1,35 +1,33 @@
-# 5.3.2 Paxos 算法
+# 6.3.2 Paxos 算法
-希望你没有对前篇 Paxos 的“复杂”做的铺垫所吓倒,共识问题已经算是一个古老的领域,30 余年间已经有无数简洁直白的视频、论文等资料进行过解读[^1]。接下来,我们先了解 Paxos 基本背景,然后直面 Paxos 算法细节,最后再用具体的例子验证 Paxos 算法。
+希望你没有对前篇 Paxos 的“复杂”做的铺垫所吓倒,共识问题已经算是一个古老的领域,30 余年间已经有无数简洁直白的视频、论文等资料进行过解读[^1]。接下来,我们先了解 Paxos 基本背景,然后直面 Paxos 算法细节,最后用具体的例子验证 Paxos 算法。
## 1. Paxos 算法背景
-在 Paxos 算法中,节点分为下面三种角色:
+在 Paxos 算法中,节点分为三种角色。
-- **提议者(**Proposer):提议者是启动共识过程的节点,它提出一个值,请求其他节点对这个值进行投票,提出值的行为称为发起“提案"(Proposal),提案包含提案编号 (Proposal ID) 和提议的值 (Value)。注意的是,Paxos 算法是一个典型的为“操作转移”模型设计的算法,为简化表述,本文把提案类比成“变量赋值”操作,但你应该理解它是“操作日志”相似的概念,后面介绍的 Raft 算法中,直接就把“提案”称做“日志”了。
+- **提议者**(Proposer):提议者是启动共识过程的节点,它提出一个值,请求其他节点对这个值进行投票,提出值的行为称为发起“提案"(Proposal),提案包含提案编号 (Proposal ID) 和提议的值 (Value)。注意的是,Paxos 算法是一个典型的为“操作转移”模型设计的算法,为简化表述,本文把提案类比成“变量赋值”操作,但你应该理解它是“操作日志”相似的概念,后面介绍的 Raft 算法中,直接就把“提案”称做“日志”了。
- **决策者**(Acceptor):接受或拒绝提议者发起的提案,如果一个提案被超过半数的决策者接受,意味着提案被“批准”(accepted)。提案一旦被批准,意味着在所有节点中达到共识,便不可改变、永久生效。
- **记录者**(Learner):记录者不发起提案,也不参与决策提案,它们学习、记录被批准的提案。
-在 Paxos 算法中,节点都是平等的,它们都可以承担一种或者多种角色。例如,提议者即可发起提案,也可以就一个提案进行表决,但为了 Quorum 的计算更加明确,表决提案的节点数最好是奇数个。
+在 Paxos 算法中,所有节点都是平等的,能够承担一种或多种角色。例如,提议者既可以发起提案,也可以对其他提案进行表决。但为了更明确地计算 Quorum,通常建议表决提案的节点数为奇数。
-Paxos 是基于 Quorum 的算法,但“少数服从多数”并不能解决所有的问题。例如,由于并发操作导致的提案冲突。
-
-如图 5-5 所示,S~1~ 向 S~1~、S~2~、S~3~ 发起提案(red)。同时,S~5~ 也向 S~3~、S~4~、S~5~ 发起提案(blue)。它们的提案 Quorum 都达成了,也就是说一个提案有两个值被批准,这显然破坏了一致性原则。
+在 Paxos 算法中,所有节点都可以发起提案。如果两个节点同时发起提案,就会导致提案冲突。如图 6-5 所示,S~1~ 向 S~1~、S~2~、S~3~ 发起提案(red)。同时,S~5~ 也向 S~3~、S~4~、S~5~ 发起提案(blue)。它们的提案 Quorum 都达成了,也就是说一个提案有两个值被批准,这显然破坏了一致性原则。
:::center

- 图 5-5 网络延迟导致冲突
+ 图 6-5 网络延迟导致冲突
:::
-根据图 5-5,你会发现提案冲突发生在 S~3~,S~3~ 是两个 Quorum 的交集点,它的时间线上有两个不同的值被批准。
+根据图 6-5,你会发现提案冲突发生在 S~3~,S~3~ 是两个 Quorum 的交集点,它的时间线上有两个不同的值被批准。
-我们知道,设计程序的一个基本常识是,如果多个线程同时操作某个共享变量,一定要加上互斥锁,不然会出现各种意外情况。不难发现,S~3~ 问题的本质是:“在分布式环境下并发操作共享变量的问题”。
+我们知道,设计程序的一个基本常识是,**如果多个线程同时操作某个共享变量,一定要加上互斥锁,不然会出现各种意外情况**。不难发现,S~3~ 问题的本质是“在分布式环境下并发操作共享变量的问题”。
-因为分布式环境下随时可能出现通信故障,我们不能“套用”进程加锁的机制解决 S~3~ 的问题。举个例子,假如一个节点获得锁之后,释放锁之前故障了。那么,整个系统就会被无限期等待阻塞。
+由于分布式环境中随时可能发生通信故障,我们不能粗暴“套用”进程加锁机制来解决 S~3~ 的问题。举个例子,如果一个节点在获得锁后故障,且在释放锁之前发生故障,整个系统可能会陷入无限期的阻塞状态。
解决上述问题的关键在于,得有一种可供其他节点抢占锁的机制,避免因通信故障导致死锁。
-笔者在本书第四章 4.2 节 介绍过“乐观锁”。分布式抢占锁的设计思想和“乐观锁”有异曲同工之妙。回顾乐观锁的示例 SQL,WHERE 条件的作用是判断在它操作之前,数据是否被修改。如果修改过,则请求最新的数据,更新版本号,然后用重试的方式再次修改。
+在本书第五章第 5.2 节中,笔者介绍了“乐观锁”。分布式抢占锁的设计思想与“乐观锁”有异曲同工之妙。回顾乐观锁的示例 SQL,WHERE 条件用于判断在操作之前数据是否已被修改。如果数据已被修改,则请求最新的数据,更新版本号,并通过重试机制再次进行修改。
```SQL
UPDATE accounts
@@ -38,11 +36,11 @@ SET balance = balance + ?,
WHERE id = ? AND version = ?;
```
-我们可以借鉴“乐观锁”的思路,尝试解决图 5-5 所示的冲突问题。请看下面的操作:
+我们可以借鉴“乐观锁”的思路,尝试解决图 6-5 所示的冲突问题。
首先,S~1~ 发起提案,S~3~ 收到 S~1~ 提案时,应该意识到 S~5~ 发起的提案(blue)的 Quorum 已经达成,S~1~ 提案(red)已经失效。根据先到先得原则,S~1~ 应该更新自己的提案值(red 替换为 blue),这个操作相当于对提案编号(乐观锁中的 version)“锁定”,防止之后出现多个冲突的提案编号。
-了解接受了哪些编,接下来的处理就简单了。现在,我们可以直面 Paxos 算法的细节了。
+一旦了解了哪些提案被接受,接下来的处理就变得简单了。现在,我们可以直面 Paxos 算法的细节了。
## 2. Paxos 算法描述
@@ -60,7 +58,7 @@ Paxos 算法的第二个阶段称“批准阶段”(Accept)。提议者向
:::center

- 图 5-6 Paxos 算法流程
+ 图 6-6 Paxos 算法流程
:::
## 3. Paxos 算法验证
@@ -71,43 +69,42 @@ Paxos 算法的第二个阶段称“批准阶段”(Accept)。提议者向
现在,我们来分析 S~1~ 、S~5~ 同时发起提案,会出现什么情况。
-**情况一:提案已批准**。如图 5-7 所示,S~1~ 收到客户端的请求,于是 S~1~ 作为提议者,向 S~1~...S~3~ 广播 Prepare(3.1) 消息,决策者 S~1~...S~3~ 没有接受过任何提案,所以接受该提案。接着,S~1~ 广播 Accept(3.1, X) 消息,提案 X 成功被批准。
+**情况一:提案已批准**。如图 6-7 所示,S~1~ 收到客户端的请求,于是 S~1~ 作为提议者,向 S~1~...S~3~ 广播 Prepare(3.1) 消息,决策者 S~1~...S~3~ 没有接受过任何提案,所以接受该提案。接着,S~1~ 广播 Accept(3.1, X) 消息,提案 X 成功被批准。
在提案 X 被批准后,S~5~ 收到客户端的提案 Y,S~5~ 作为提议者向 S~3~...S~5~ 广播 Prepare(4.5) 消息。对 S~3~ 来说,4.5 比 3.1 大,且已经接受了 X,它回复提案 (3.1, X)。S~5~ 收到 S~3~...S~5~ 的回复后,使用 X 替换自己的 Y,接着进入批准阶段,广播 Accept(4.5, X) 消息。S~3~...S~5~ 批准提案,所有决策者就 X 达成一致。
:::center

- 图 5-7 提案已批准
+ 图 6-7 提案已批准
:::
-**情况二:事实上,对于情况一,也就是“取值为 X”并不是一定需要多数派批准,S~5~ 发起提案时,准备阶段的应答中是否包含了批准过 X 的决策者也影响决策**。如图 5-8 所示,S~3~ 接受了提案 (3.1, X),但 S~1~、S~2~ 还没有收到 Accept(3.1, X) 消息。此时 S~3~、S~4~、S~5~ 收到 Prepare(4.5) 消息,S~3~ 回复已经接受的提案 (3.1, X),S~5~ 将提案值 Y 替换成 X,广播 Accept(4.5, X) 消息给 S~3~、S~4~、S~5~,对 S~3~ 来说,编号 4.5 大于 3.1,所以批准提案 X,最终共识的结果仍然是 X。
+**情况二:事实上,对于情况一,也就是“取值为 X”并不是一定需要多数派批准,S~5~ 发起提案时,准备阶段的应答中是否包含了批准过 X 的决策者也影响决策**。如图 6-8 所示,S~3~ 接受了提案 (3.1, X),但 S~1~、S~2~ 还没有收到 Accept(3.1, X) 消息。此时 S~3~、S~4~、S~5~ 收到 Prepare(4.5) 消息,S~3~ 回复已经接受的提案 (3.1, X),S~5~ 将提案值 Y 替换成 X,广播 Accept(4.5, X) 消息给 S~3~、S~4~、S~5~,对 S~3~ 来说,编号 4.5 大于 3.1,所以批准提案 X,最终共识的结果仍然是 X。
:::center

- 图 5-8 提案部分接受,新提议者可见
+ 图 6-8 提案部分接受,新提议者可见
:::
**情况三:另外一种可能的情况是 S~5~ 发起提案时,准备阶段的应答中未包含批准过 X 的决策节点**。S~1~ 接受了提案 (3.1, X),S~3~ 先收到 Prepare(4.5) 消息,后收到 Accept(3.1, X) 消息,由于 3.1 小于 4.5,会直接拒绝这个提案。提案 X 没有收到多数的回复,X 提案就被阻止了。提案 Y 顺利通过,整个系统最终对“取值为 Y”达成一致。
:::center

- 图 5-9 提案部分接受,新提议者不可见
+ 图 6-9 提案部分接受,新提议者不可见
:::
-
**情况四:从情况三可以推导出另一种极端的情况**,多个提议者同时发起提案,在准备阶段互相抢占,反复刷新决策者上的提案编号,导致任何一方都无法达到多数派决议,这个过程理论上可以无限持续下去,形成“活锁”(livelock)。
解决这个问题并不复杂,将重试时间随机化,就能减少这种巧合发生。
:::center

- 图 5-10 出现活锁问题
+ 图 6-10 出现活锁问题
:::
以上,就是整个 Paxos 算法的工作原理。
-Paxos 的价值在于推动了分布式共识算法的发展,但它有以下缺陷:只能处理单一提案,且达成共识至少需要两次网络往返,高并发情况下可能导致活锁。因此,Paxos 算法主要用于理论研究,较少直接应用于工程实践。为了应对多次提案和大规模分布式系统的需求,Lamport 在论文《Paxos Made Simple》中提出了 Paxos 的优化变体 —— Multi Paxos。Multi Paxos 引入了“选主”机制,通过多次运行 Paxos 算法来处理多个提案。
+Paxos 算法只能处理单个提案,达成共识至少需要两次网络往返,高并发情况下还可能导致活锁。因此,Paxos 算法主要用于理论研究,很少直接用于工程实践。后来,Lamport 在论文《Paxos Made Simple》中提出了 Paxos 的变体 —— Multi Paxos。Multi Paxos 引入了“选主”机制,通过多轮运行 Paxos 算法来处理多个提案。
-不过,Lamport 的论文主要关注的是 Paxos 的算法基础和正确性证明,对于领导者选举以及解决多轮提案的效率问题,并没有给出充分的实现细节。2014 年,斯坦福的学者 Diego Ongaro 和 John Ousterhout 发表了论文《In Search of an Understandable Consensus Algorithm》,该论文基于 Multi Paxos 思想,提出了“选主”、“日志复制”等概念及其实现细节,提出了简化和改进版的 Raft 算法。该论文斩获 USENIX ATC 2014 大会 Best Paper 荣誉,Raft 算法更是成为后来 etcd、Consul 等分布式系统的实现基础。
+不过,Lamport 的论文主要聚焦于 Paxos 正确性证明,对于领导者选举、多轮提案并没有给出实现细节。2014 年,斯坦福的学者 Diego Ongaro 和 John Ousterhout 发表了论文《In Search of an Understandable Consensus Algorithm》,该论文基于 Multi Paxos 思想,提出了“选主”、“日志复制”的概念,并给出了详细的实现细节。该论文斩获 USENIX ATC 2014 大会 Best Paper 荣誉,更是成为后来 etcd、Consul 等分布式系统的实现基础。
[^1]: 讲解作者是斯坦福教授 John Ousterhunt,他还指导了 Diego Ongaro 写出了 Raft 的论文。本章配图也多来源于 John Ousterhunt 所发表的内容。
diff --git a/consensus/Paxos-history.md b/consensus/Paxos-history.md
index 288a9e03..f109c6b3 100644
--- a/consensus/Paxos-history.md
+++ b/consensus/Paxos-history.md
@@ -1,8 +1,6 @@
-# 5.3.1 Paxos 算法起源
+# 6.3.1 Paxos 算法起源
-Paxos 算法最初的论文名称为《The Part-Time Parliament》,翻译成中文为“兼职议会”。
-
-这篇论文的开头描述了一个虚构的古希腊岛屿考古发现故事。如果不事先说明,或许你根本不会意识到下面是一篇关于分布式的论文。
+Paxos 算法最初的论文名称为《The Part-Time Parliament》,翻译成中文为“兼职议会”。论文的开头描述了一个虚构的古希腊岛屿考古发现故事。如果不事先说明,你可能不会意识到这是一篇关于分布式的论文。
:::tip 《The Part-Time Parliament》
公元十世纪初,爱情海上的 Paxos 小岛是一个繁荣的商业中心。随着财富的积累,政治变得愈加复杂,Paxon 的公民用议会制政府取代了古老的神权政治。然而,商业利益高于公民义务,没人愿意将一生投入到议会事务中。因此,Paxon 议会必须在议员频繁进出议会的情况下,保持正常运作……
@@ -12,7 +10,7 @@ Paxos 算法最初的论文名称为《The Part-Time Parliament》,翻译成
1990 年,Lamport 将《The Part-Time Parliament》论文提交给 TOCS 期刊。根据 Lamport 的本人的回忆[^1],TOCS 审稿人阅读后认为“这篇论文不怎么重要,但还有些意思”,并建议删掉与 Paxos 相关的故事背景。Lamport 对这些缺乏幽默感的审稿人颇为不爽,拒绝对论文进行修改。于是,论文的发表被搁置。
-虽然论文没有发表,但不代表没有人关注这个算法,Bulter W.Lampson(1991 年图灵奖获得者)认识到 Paxos 算法的重要性,在他的论文《How to Build a Highly Availability System using Consensus》对 Paxos 算法进行了讲述。后来,De Prisco、Lynch 和 Lampson 几人联合在《理论计算机科学》期刊发表了论文《Revisiting the PAXOS algorithm》对 Paxos 算法进行了详细地描述和证明。经过 Lampson 等人的大力宣传,Paxos 算法逐渐被学术界重视。
+虽然论文没有发表,但不代表没有人关注这个算法。Bulter W.Lampson(1991 年图灵奖获得者)认识到 Paxos 算法的重要性,在他的论文《How to Build a Highly Availability System using Consensus》对 Paxos 算法进行了讲述。后来,De Prisco、Lynch 和 Lampson 几人联合在《理论计算机科学》期刊发表了论文《Revisiting the PAXOS algorithm》对 Paxos 算法进行了详细地描述和证明。经过 Lampson 等人的大力宣传,Paxos 算法逐渐被学术界重视。
另一方面,这些介绍 Paxos 算法的论文使 Lamport 觉得《The Part-Time Parliament》重新发表的时间到了。
@@ -34,10 +32,10 @@ Paxos 算法最初的论文名称为《The Part-Time Parliament》,翻译成
:::center

- 图 5-4 《Paxos Made Simple》论文摘要
+ 图 6-4 《Paxos Made Simple》论文摘要
:::
-然而,这篇论文还是非常难以理解,引用斯坦福大学学者 Diego Ongaro 和 John Ousterhout 在设计 Raft 时的论文[^4]中对 Paxos 的描述:
+然而,这篇论文还是非常难以理解,引用斯坦福大学学者 Diego Ongaro 和 John Ousterhout 在设计 Raft 时的论文[^4]中对 Paxos 的描述。
:::tip 《In Search of an Understandable Consensus Algorithm》节选
@@ -50,7 +48,7 @@ we were not able to understand the complete protocol until after reading several
连斯坦福的教授和博士都感觉难以理解。所以,他们的论文取名《In Search of an Understandable Consensus Algorithm》,意思是“易懂的共识算法还在寻找中”,根本不像 Lamport 说的那么简单。
-注意 Raft 论文发表于 2013 年,而论文《Paxos Made Simple》是 2001 年发表的,也就是说 Paxos 算法已经被研究了十几年,直到 Google 的分布式锁服务 Chubby 横空出世,Chubby 使用 Paxos 共识算法实现强一致性,帮助 Google 解决了分布式系统中的资源协调问题。得益于 Google 的行业影响力,辅以 Chubby 作者 Mike Burrows 那略显夸张但足够吸引眼球的评价推波助澜,Paxos 算法从理论进入工业实践,逐渐被大家熟知和认可。
+注意,Raft 论文发表于 2013 年,而论文《Paxos Made Simple》是 2001 年发表的。也就是说,Paxos 算法已经被研究了十几年。直到 Google 的分布式锁服务 Chubby 横空出世,Chubby 使用 Paxos 共识算法实现强一致性,帮助 Google 解决了分布式系统中的资源协调问题。得益于 Google 的行业影响力,辅以 Chubby 作者 Mike Burrows 那略显夸张但足够吸引眼球的评价推波助澜,Paxos 算法从理论进入工业实践,逐渐被大家熟知和认可。
最终,Lamport 凭借他在分布式领域的贡献,于 2013 年获得图灵奖。
diff --git a/consensus/Paxos.md b/consensus/Paxos.md
index ebd8b73e..337e9784 100644
--- a/consensus/Paxos.md
+++ b/consensus/Paxos.md
@@ -1,4 +1,4 @@
-# 5.3 Paxos 算法
+# 6.3 Paxos 算法
Paxos 算法由 Leslie Lamport[^1] 于 1990 年提出,是一种基于消息传递、具备高度容错特性的共识算法。该算法是当今分布式系统最重要的理论基础,几乎就是“共识系统”的代名词。
diff --git a/consensus/Replicated-State-Machine.md b/consensus/Replicated-State-Machine.md
index 96e47a78..e4aa5719 100644
--- a/consensus/Replicated-State-Machine.md
+++ b/consensus/Replicated-State-Machine.md
@@ -1,29 +1,28 @@
-# 5.2 日志与复制状态机
+# 6.2 日志与复制状态机
如果统计分布式系统有多少块基石,“日志”一定是其中之一。
这里“日志”并不是常见的通过 log4j 或 syslog 输出的文本。而是 MySQL 中的 binlog(Binary Log)、MongoDB 中的 Oplog(Operations Log)、Redis 中的 AOF(Append Only File)、PostgreSQL 中的 WAL(Write-Ahead Log)...。它们虽然名称不同,但共同特点是**只能追加、完全有序的记录序列**。
-根据图 5-1 展示了日志结构,可以看出日志是有序的、持久化的记录序列,增加记录时从末尾追加,读取时“从左到右”顺序扫描。
+图 6-1 展示了日志的结构,可以看出,日志是有序且持久化的记录序列。新记录会从末尾追加,而读取时则按“从左到右”的顺序进行扫描。
:::center

- 图 5-1 日志是有序的、持久化的记录序列 [图片来源](https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying)
+ 图 6-1 日志是有序的、持久化的记录序列 [图片来源](https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying)
:::
-有序的日志记录了“什么时间发生了什么”,这句话通过下面两种数据复制模型来理解:
-
-- **主备模型(Primary-backup)**:又称“状态转移”模型,主节点(Master)负责执行如“+1”、“-2”的操作,将操作结果(如“1”、“3”、“6”)记录到日志中,备节点(Slave)根据日志直接同步结果;
-- **复制状态机模型(State-Machine Replication)**:又称“操作转移”模型,日志记录的不是最终结果,而是具体的操作指令,如“+1”、“-2”。指令按照顺序被依次复制到各个节点(Peer)。如果每个节点按顺序执行这些指令,各个节点最终将达到一致的状态。
+有序的日志记录了“何时发生了什么”,这一点可以通过以下两种数据复制模型来理解。
+- **主备模型**(Primary-backup):又称“状态转移”模型,主节点(Master)负责执行如“+1”、“-2”的操作,将操作结果(如“1”、“3”、“6”)记录到日志中,备节点(Slave)根据日志直接同步结果。
+- **复制状态机模型**(State-Machine Replication):又称“操作转移”模型,日志记录的不是最终结果,而是具体的操作指令,如“+1”、“-2”。指令按照顺序被依次复制到各个节点(Peer)。如果每个节点按顺序执行这些指令,各个节点最终将达到一致的状态。
:::center

- 图 5-2 分布式系统数据复制模型
+ 图 6-2 分布式系统数据复制模型
:::
无论哪一种模型,它们都揭示了:“**顺序是节点之间保持一致性的关键因素**”。如果打乱了操作的顺序,就会得到不同的运算结果。
-进一步解释以“复制状态机”(State Machine Replication)工作模型构建的分布式系统,其原理如图 5-3 所示。
+接下来,进一步解释基于“复制状态机”(State Machine Replication)工作模型构建的分布式系统,其基本原理如图 6-3 所示。
:::tip 复制状态机的基本原理
两个“相同的” (identical)、“确定的” (deterministic) 进程:
@@ -32,20 +31,20 @@
- 确定的:进程的行为是完全可预测的,不能有任何非确定性的逻辑,比如随机数生成或不受控制的时间依赖。
如果它们以相同的状态启动,按相同的顺序获取相同的输入。那么,它们一定会达到相同的状态。
-
:::
共识算法(图中的 Consensus Module,Paxos 或者 Raft 算法)通过消息,将日志广播至所有节点,它们就日志什么位置,记录什么(序号为 9,执行 set x=3)达成共识。换句话说,所有的节点中,都有着相同顺序的日志序列,
```json
-{ "index": 9, "command": "set x=3" },
+// 日志
+{ "index": 9, "command": "set x=3" }
```
-节点内的进程(图中的 State Machine)依次执行日志序列,操作是全局顺序的。那么,所有节点最终一定成一致的状态。多个这样的进程加上有序的日志,就组成了如 Apache Kafka、Zookeeper、etcd、CockroachDB 等分布式系统中的关键组件。
+节点内的进程(图中的 State Machine)按顺序执行日志序列,操作具有全局顺序。因此,所有节点最终将达到一致的状态。多个这样的进程结合有序日志,就构成了 Apache Kafka、Zookeeper、etcd、CockroachDB 等分布式系统中的关键组件。
:::center

- 图 5-3 复制状态机工作模型 [图片来源](https://raft.github.io/raft.pdf)
+ 图 6-3 复制状态机工作模型 [图片来源](https://raft.github.io/raft.pdf)
:::
[^1]: https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying
\ No newline at end of file
diff --git a/consensus/conclusion.md b/consensus/conclusion.md
index 56a344fa..93ae3d8a 100644
--- a/consensus/conclusion.md
+++ b/consensus/conclusion.md
@@ -1,9 +1,9 @@
-# 5.5 小结
+# 6.5 小结
-尽管 Paxos 算法提出已有几十年,但它为分布式共识研究奠定了基础。Paxos 基于“少数服从多数”(Quorum 机制)原则,通过“请求阶段”和“批准阶段”在不确定环境下,解决了单个“提案”的共识问题。多次运行 Paxos,便可实现一系列“提案”的共识,这就是 Multi-Paxos 的核心思想。Raft 算法在 Multi-Paxos 的基础上,在一致性、安全性和可理解性之间找到平衡,成为业界广泛采用的主流选择。
+尽管 Paxos 算法已提出几十年,但它为分布式系统中的一致性与容错性问题提供了理论框架,并开创了分布式共识研究的先河。
-接下来,再思考一个问题,Raft 算法属于“强领导者”模型,领导者负责所有写入操作,它的写瓶颈就是 Raft 集群的写瓶颈。那么,该如何突破 Raft 集群的写瓶颈呢?
+Paxos 基于“少数服从多数”(Quorum 机制)原则,通过“请求阶段”和“批准阶段”在不确定环境下,解决了单个“提案”的共识问题。多次运行 Paxos,便可实现一系列“提案”的共识,这就是 Multi-Paxos 的核心思想。Raft 算法在 Multi-Paxos 的基础上,在一致性、安全性和可理解性之间找到平衡,成为业界广泛采用的主流选择。
-一种方法是使用哈希算法将数据划分成多个独立部分(分片)。例如,将一个 100TB 规模数据的系统分成 10 部分,每部分只需处理 10TB。这种根据规则(范围或哈希)将数据分散处理的策略,被称为“分片机制”(Sharding)。分片机制广泛应用于 Prometheus、Elasticsearch 、ClickHouse 等大数据系统(详见本书第九章)。理论上,只要机器数量足够,分片机制便能支持几乎无限规模的数据。
+接下来,再思考一个问题,Raft 算法属于“强领导者”模型,领导者负责所有写入操作,它的写瓶颈就是 Raft 集群的写瓶颈。那么,该如何突破 Raft 集群的写瓶颈呢?
-解决了数据规模的问题,接下来的课题是“将请求均匀地分摊至各个分片”。这部分内容,笔者将在下一章《负载均衡与代理技术》展开讨论。
\ No newline at end of file
+一种方法是使用哈希算法将数据划分成多个独立部分(分片)。例如,将一个 100TB 规模数据的系统分成 10 部分,每部分只需处理 10TB。这种根据规则(范围或哈希)将数据分散处理的策略,被称为“分片机制”(Sharding)。分片机制广泛应用于 Prometheus、Elasticsearch 、ClickHouse 等大数据系统(详见本书第九章)。理论上,只要机器数量足够,分片机制就能支持任意规模的数据。
diff --git a/consensus/consensus.md b/consensus/consensus.md
index ecca7f67..10ac87fb 100644
--- a/consensus/consensus.md
+++ b/consensus/consensus.md
@@ -1,26 +1,24 @@
-# 5.1 什么是共识
+# 6.1 什么是共识
-业内讨论 Paxos 或 Raft 算法时,常使用“分布式一致性协议”或“分布式一致性算法”来描述。例如,Google Chubby 系统的作者 Mike Burrows 曾评价 Paxos:“There is only one consensus protocol...”,这一句话常被翻译为“世界上只有一种一致性算法”。
-
-尽管“共识”和“一致”在汉语中含义相近,但在计算机领域,这两个术语具有截然不同的含义:
+在业内讨论 Paxos 或 Raft 算法时,通常使用“分布式一致性协议”或“分布式一致性算法”来描述。例如,Google Chubby 系统的作者 Mike Burrows 曾评价 Paxos:“There is only one consensus protocol...”,这句话常被翻译为“世界上只有一种共识算法”。在汉语中,“共识”和“一致”意思相似,但在计算机领域,它们具有截然不同的含义。
- **共识**(Consensus):指所有节点就某项操作(如选主、原子事务提交、日志复制、分布式锁管理等)达成一致的实现过程。
- **一致性**(Consistency):描述多个节点的数据是否保持一致,关注数据最终达到稳定状态的结果。
本书第五章介绍的 CAP 定理中的 C 和数据库 ACID 模型中的 C 描述的是数据“一致性”属性。而 Paxos、Raft 或者 ZAB 等算法研究的是如何达成一致。因此,将 Paxos 等算法归类到“共识算法”更准确。
-在分布式系统中,节点故障不可避免,但部分节点故障不应该影响系统整体状态。通过增加节点数量,依据“少数服从多数”原则,只要多数节点(至少 $\mathit{N/2+1}$)达成一致,其状态即可代表整个系统。这种依赖多数节点实现容错的机制称为 Quorum 机制。
+在分布式系统中,节点故障是不可避免的,但部分节点故障不应该影响系统整体状态。通过增加节点数量,依据“少数服从多数”原则,只要多数节点(至少 $\mathit{N/2+1}$)达成一致,其状态即可代表整个系统。这种依赖多数节点实现容错的机制称为 Quorum 机制。
:::tip Quorum 机制
-- 3 节点集群:Quorum 为 2,允许 1 个节点故障;
-- 4 节点集群:Quorum 为 $\mathit{⌈4/2⌉+1 = 3}$,允许 1 个节点故障;
+- 3 节点集群:Quorum 为 2,允许 1 个节点故障。
+- 4 节点集群:Quorum 为 $\mathit{⌈4/2⌉+1 = 3}$,允许 1 个节点故障。
- 5 节点集群:Quorum 为 $\mathit{⌈5/2⌉+1 = 3}$,允许 2 个节点故障。
-节点个数为 $\mathit{N}$ 的集群,能容忍 $\mathit{(N-1)/2}$ 个节点故障。你注意到了么?3 节点和 4 节点集群的故障容忍性一致。所以,一般情况下,以容错为目的的分布式系统没必要使用 4 个节点。
+集群节点个数为 $\mathit{N}$ ,能容忍 $\mathit{(N-1)/2}$ 个节点故障。你注意到了吗?3 节点和 4 节点集群的故障容忍能力一样。因此,通常情况下,针对容错的分布式系统无需使用 4 个节点。
:::
-基于 Quorum 的机制,通过“少数服从多数”协商机制达成一致的决策,从而对外表现为一致的运行结果。这一过程被称为节点间的“协商共识”。一旦解决共识问题,便可提供一套屏蔽内部复杂性的抽象机制,为应用层提供一致性保证,满足多种需求,例如:
+基于 Quorum 的机制,通过“少数服从多数”协商机制达成一致的决策,从而对外表现为一致的运行结果。这一过程被称为节点间的“协商共识”。一旦解决共识问题,便可提供一套屏蔽内部复杂性的抽象机制,为应用层提供一致性保证,满足多种需求。
- **主节点选举**:在主从复制数据库中,所有节点需要就“谁来当主节点”达成一致。如果由于网络问题导致节点间无法通信,很容易引发争议。若争议未解决,可能会出现多个节点同时认为自己是主节点的情况,这就是分布式系统中最棘手的问题之一 —— “脑裂”。
- **原子事务提交**:对于支持跨节点或跨分区事务的数据库,可能会发生部分节点事务成功、部分节点事务失败的情况。为维护事务的原子性(即 ACID 特性),所有节点必须就事务的最终结果达成一致。
- **分布式锁管理**:当多个请求尝试访问共享资源时,共识机制可确保所有节点一致认定“谁成功获取了锁”。即使发生网络故障或节点异常,也能避免锁争议,从而防止并发冲突或数据不一致。
diff --git a/consensus/raft-ConfChange.md b/consensus/raft-ConfChange.md
index 8494bd0a..02645b96 100644
--- a/consensus/raft-ConfChange.md
+++ b/consensus/raft-ConfChange.md
@@ -1,8 +1,8 @@
-# 5.4.3 成员变更
+# 6.4.3 成员变更
在前面的内容中,我们假设集群节点数固定,即集群的 Quorum 也保持不变。然而,在生产环境中,集群通常需要进行节点变更,例如因故障移除节点或扩容增加节点等。对于旨在实现容错能力的算法来说,显然不能通过“关闭集群、更新配置并重启系统”的方式来实现。
-在讨论如何实现成员动态变更之前,我们首先需要搞明白 Raft 集群中“配置”(configuration)的概念。
+在讨论如何实现成员动态变更之前,我们需要先搞明白 Raft 集群中“配置”(configuration)的概念。
:::tip 配置
配置说明集群由哪些节点组成。例如,一个集群有三个节点(Server 1、Server 2、Server 3),该集群的配置就是 [Server1、Server2、Server3]。
@@ -21,22 +21,22 @@
:::center

- 图 5-15 某一时刻,集群存在两个 Quorum
+ 图 6-15 某一时刻,集群存在两个 Quorum
:::
上述问题的根本原因在于,成员变更过程中形成了两个没有交集的 Quorum,即 [Server1, Server2] 和 [Server3, Server4, Server5] 各自为营。
Raft 的论文中,对此提出过一种基于两阶段的“联合共识”(Joint Consensus)成员变更方案,但这种方案实现较为复杂,Diego Ongaro 后来又提出一种更为简化的方案 — “单成员变更”(Single Server Changes)。该方案思想的核心是,既然同时提交多个成员变更可能引发问题,那么每次只提交一个成员变更,需要添加多个成员,就执行多次单成员变更操作。这样不就没有问题了么!
-单成员变更方案很容易穷举所有情况,如图 5-22 所示,穷举奇/偶数集群下节点添加/删除情况。如果每次只操作一个节点,C~old~ 的 Quorum 和 C~new~ 的 Quorum 一定存在交集。交集节点只会进行一次投票,要么投票给 C~old~,要么投票给 C~new~。因此,不可能出现两个符合条件的 Quorum,也就不会出现两个领导者。
+单成员变更方案很容易穷举所有情况,如图 6-16 所示,穷举奇/偶数集群下节点添加/删除情况。如果每次只操作一个节点,C~old~ 的 Quorum 和 C~new~ 的 Quorum 一定存在交集。交集节点只会进行一次投票,要么投票给 C~old~,要么投票给 C~new~。因此,不可能出现两个符合条件的 Quorum,也就不会出现两个领导者。
-以图 5-16 第二种情况为例,C~old~ 为 [Server1、Server2、Server3],该配置的 Quorum 为 2,C~new~ 为 [Server1、Server2、Server3、Server4],该配置的 Quorum 为 3。假设 Server1、Server2 比较迟钝,还在用 C~old~ ,其他节点的状态机已经应用 C~new~:
+以图 6-16 第二种情况为例,C~old~ 为 [Server1、Server2、Server3],该配置的 Quorum 为 2,C~new~ 为 [Server1、Server2、Server3、Server4],该配置的 Quorum 为 3。假设 Server1、Server2 比较迟钝,还在用 C~old~ ,其他节点的状态机已经应用 C~new~:
- 假设 Server1 触发选举,赢得 Server1,Server2 的投票,满足 C~old~ Quorum 要求,当选领导者;
- 假设 Server3 也触发选举,赢得 Server3,Server4 的投票,但**不满足 C~new~ 的 Quorum 要求,选举失效**。
:::center

- 图 5-16 穷举奇/偶数集群下节点添加/删除情况
+ 图 6-16 穷举奇/偶数集群下节点添加/删除情况
:::
目前,绝大多数 Raft 算法的实现和系统,如 HashiCorp Raft 和 etcd,均采用单节点变更方案。由于联合共识方案的复杂性和实现难度,本文不再深入讨论,有兴趣的读者可以参考 Raft 论文以了解更多细节。
\ No newline at end of file
diff --git a/consensus/raft-leader-election.md b/consensus/raft-leader-election.md
index 2b751837..92558a21 100644
--- a/consensus/raft-leader-election.md
+++ b/consensus/raft-leader-election.md
@@ -1,8 +1,8 @@
-# 5.4.1 领导者选举
+# 6.4.1 领导者选举
Paxos 算法中“节点众生平等”,每个节点都可以发起提案。多个提议者并行发起提案,是活锁、以及其他异常问题的源头。那如何不破坏 Paxos 的“节点众生平等”基本原则,又能在提案节点中实现主次之分,约束提案权利?
-Raft 对此的设计是明确领导者、通过选举机制“分享”提案权利。直接来看 Raft 算法中节点的分类:
+理解上面的问题,是先搞清楚 Raft 算法中节点的分类。Raft 提出了领导者角色,通过选举机制“分享”提案权利。
- **领导者**(Leader):负责处理所有客户端请求,将请求转换为“日志”复制到其他节点,不断地向所有节点广播心跳消息:“你们的领导还在,不要发起新的选举”。
- **跟随者**(Follower):接收、处理领导者的消息,并向领导者反馈日志的写入情况。当领导者心跳超时时,他会主动站起来,推荐自己成为候选人。
@@ -10,23 +10,23 @@ Raft 对此的设计是明确领导者、通过选举机制“分享”提案权
联想到现实世界中的领导人都有一段不等的任期。自然,Raft 算法中也对应的概念 —— “任期”(term)。Raft 中的任期是一个递增的数字,贯穿于 Raft 的选举、日志复制和一致性维护过程中。
-- 选举过程:任期确保了领导者的唯一性。在一次任期内,只有获得多数选票的节点才能成为领导者。
-- 日志一致性:任期号会附加到每条日志条目中,帮助集群判断日志的最新程度。
-- 冲突检测:通过比较任期号,节点可以快速判断自己是否落后,并切换到跟随者状态。
+- **选举过程**:任期确保了领导者的唯一性。在一次任期内,只有获得多数选票的节点才能成为领导者。
+- **日志一致性**:任期号会附加到每条日志条目中,帮助集群判断日志的最新程度。
+- **冲突检测**:通过比较任期号,节点可以快速判断自己是否落后,并切换到跟随者状态。
:::center

- 图 5-11 Raft 通过任期区分和管理集群中领导者的生命周期
+ 图 6-11 Raft 中的任期
:::
-图 5-12 概述了 Raft 集群 Leader 选举过程。
+图 6-12 概述了 Raft 集群 Leader 选举过程。
:::center

- 图 5-12 Raft 选举过程
+ 图 6-12 Raft 选举过程
:::
-初始状态下,所有的节点处于跟随者状态。如果跟随者在某个时限(通常是 150-300 毫秒的随机超时时间)未收到领导者心跳,则触发触发选举。节点的角色转为 候选者,任期号递增,然后向其他节点广播“投票给我”的消息(RequestVote RPC)。
+初始状态下,所有的节点处于跟随者状态。如果跟随者在某个时限(通常是 150-300 毫秒的随机超时时间)未收到领导者心跳,则触发触发选举。节点的角色转为候选者,任期号递增,然后向其他节点广播“投票给我”的消息(RequestVote RPC)。
RequestVote RPC 消息示例如下:
diff --git a/consensus/raft-log-replication.md b/consensus/raft-log-replication.md
index 67e274f1..b44e7265 100644
--- a/consensus/raft-log-replication.md
+++ b/consensus/raft-log-replication.md
@@ -1,8 +1,8 @@
-# 5.4.2 日志复制
+# 6.4.2 日志复制
一旦选出一个公认的领导者,那领导者顺理其章地承担起“**处理系统发生的所有变更,并将变更复制到所有跟随者节点**”的职责。
-在 Raft 算法中,日志承载着系统所有变更。图 5-13 展示了 Raft 集群的日志模型,每个“日志条目”(log entry)包含索引、任期、指令等关键信息:
+在 Raft 算法中,日志承载着系统所有变更。图 6-13 展示了 Raft 集群的日志模型,每个“日志条目”(log entry)包含索引、任期、指令等关键信息:
- **指令**: 表示客户端请求的具体操作内容,也就是待“状态机”(State Machine)执行的操作。
- **索引值**:日志条目在仓库中的索引值,是单调递增的数字。
@@ -10,7 +10,7 @@
:::center

- 图 5-13 Raft 集群的日志模型(x ← 3 代表x赋值为3)
+ 图 6-13 Raft 集群的日志模型(x ← 3 代表x赋值为3)
:::
Raft 算法中,领导者通过广播消息(AppendEntries RPC)将日志条目复制到所有跟随者。AppendEntries RPC 的示例如下:
@@ -27,7 +27,7 @@ Raft 算法中,领导者通过广播消息(AppendEntries RPC)将日志条
}
```
-根据图 5-14 所示,当 Raft 集群收到客户端请求(例如 set x=4)时,日志复制的过程如下:
+根据图 6-14 所示,当 Raft 集群收到客户端请求(例如 set x=4)时,日志复制的过程如下:
- 若当前节点非领导者,将请求转发至领导者;
- 领导者接收请求后:
@@ -38,7 +38,7 @@ Raft 算法中,领导者通过广播消息(AppendEntries RPC)将日志条
:::center

- 图 5-14 日志复制的过程
+ 图 6-14 日志复制的过程
:::
diff --git a/consensus/raft.md b/consensus/raft.md
index 51069242..7f8bcbd2 100644
--- a/consensus/raft.md
+++ b/consensus/raft.md
@@ -1,4 +1,4 @@
-# 5.4 Raft 算法
+# 6.4 Raft 算法
:::tip 额外知识
Raft 是由 Re{liable|plicated|dundant} And Fault-Tolerant 组合起来的单词,意思是可靠、复制、冗余和容错。同时,Raft 在英文有“筏”的含义,隐喻一艘帮助你逃离 Paxos 小岛的救生筏。
@@ -8,15 +8,17 @@ Raft 是由 Re{liable|plicated|dundant} And Fault-Tolerant 组合起来的单词
Raft 算法出现之前,绝大多数共识系统都是基于 Paxos 算法或者受其影响。同时,Paxos 算法也成为教学领域里讲解共识问题时的范例。不幸的是,Paxos 算法理解起来非常晦涩。此外,论文虽然提到了 Multi Paxos,但缺少实现细节。因此,无论是学术界还是工业界普遍对 Paxos 算法感到十分头疼。
-那段时期,虽然所有的共识系统都是从 Paxos 算法开始的,但工程师们实现过程中有很多难以逾越的难题,往往不得已开发出与 Paxos 完全不一样的算法,这导致 Lamport 的证明并没有太大价值。所以很长的一段时间内,并没有一个被大众广泛认同的 Paxos 算法。
+那段时期,虽然所有的共识系统都是从 Paxos 算法开始的,但工程师们实现过程中有很多难以逾越的难题,往往不得已开发出与 Paxos 完全不一样的算法,这导致 Lamport 的证明并没有太大价值。所以,很长的一段时间内,实际上并没有一个被大众广泛认同的 Paxos 算法。
-:::tip Chubby 作者评论 Paxos
+:::tip
Paxos 算法的理论描述与实际工程实现之间存在巨大鸿沟,最终实现的系统往往建立在一个尚未完全证明的算法基础之上。
+:::right
+—— Chubby 作者评论 Paxos
:::
考虑到共识问题在分布式系统的重要性,同时为了提供一种更易于理解的教学方法,斯坦福大学的学者们决定重新设计一个替代 Paxos 的共识算法。
-2013 年,斯坦福大学的学者 Diego Ongaro 和 John Ousterhout 发表了论文 《In Search of an Understandable Consensus Algorithm》[^1],提出了 Raft 算法。Raft 论文开篇描述了 Raft 的证明和 Paxos 等价,详细阐述了算法如何实现。也就是说,Raft 天生就是 Paxos 算法的工程化的一种样子。
+2013 年,斯坦福大学的学者 Diego Ongaro 和 John Ousterhout 发表了论文 《In Search of an Understandable Consensus Algorithm》[^1],提出了 Raft 算法。Raft 论文开篇描述了 Raft 的证明和 Paxos 等价,详细阐述了算法如何实现。也就是说,Raft 天生就是 Paxos 算法的工程化。
:::tip 《In Search of an Understandable Consensus Algorithm》开篇
Raft is a consensus algorithm for managing a replicated log. It produces a result **equivalent to (multi-)Paxos, and it is as efficient as Paxos,** but its structure is different from Paxos;
diff --git a/consensus/summary.md b/consensus/summary.md
index 4d3039cf..d641f601 100644
--- a/consensus/summary.md
+++ b/consensus/summary.md
@@ -1,4 +1,4 @@
-# 第五章:分布式共识及算法
+# 第六章:分布式共识及算法
:::tip
世界上只有一种共识算法,就是 Paxos,其他所有的共识算法都是 Paxos 的退化版本。
@@ -13,5 +13,5 @@
:::center

- 图 5-0 本章内容导图
+ 图 6-0 本章内容导图
:::
\ No newline at end of file