Skip to content

Commit

Permalink
fix 分布式共识内容
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Nov 26, 2024
1 parent f7447ce commit 9a7391e
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 38 deletions.
2 changes: 1 addition & 1 deletion architecture/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

## 1.1.2 虚拟化技术成熟

Intel 创始人之一 Gordon Earle Moore 曾提出非常有名的摩尔定律,简而言之“每隔18个月,芯片的性能会增加一倍”。随着虚拟化技术的出现,我们能够更高效地利用硬件性能提升带来的丰富资源。这不仅优化了资源分配,还显著降低了企业的 IT 基础设施成本。
Intel 创始人之一 Gordon Earle Moore 曾提出非常有名的摩尔定律,简而言之“每隔18个月,芯片的性能会增加一倍”,也就是计算成本持续呈指数式下降。随着虚拟化技术的出现,我们能够更高效地利用硬件性能提升带来计算资源。这不仅优化了资源分配,还显著降低了企业的 IT 基础设施成本。

如图 1-1 所示,2000 年前后,虚拟化技术逐渐发展成熟。

Expand Down
2 changes: 1 addition & 1 deletion assets/raft-election.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion assets/raft-term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions consensus/Replicated-State-Machine.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
图 5-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
![](../assets/active_and_passive_arch.png) <br/>
Expand Down
12 changes: 8 additions & 4 deletions consensus/raft-ConfChange.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@

如果把“配置”当成 Raft 中的“特殊日志”。这样一来,成员的动态变更就可以转化为“配置日志”的一致性问题。但注意的是,节点“提交”(commit)日志是异步的,不可能同时操作。这种情况下,成员变更就会出现问题。

举一个具体的例子,假设当前 Raft 集群由 Server1(Leader)、Server2 和 Server3 组成,配置称为 C~old~,该集群 Quorum 为(N/2)+1 = 2。现在,我们计划增加两个节点,新的集群配置为[Server1、Server2、Server3、Server4、Server5],新的配置称为 C~new~,该集群 Quorum 为(N/2)+1 = 3。

由于提交日志是异步的,可能 Server3,Server4,Server5 已“提交”新配置 C~new~,而 Server1,Server2 比较迟钝,还在用老配置 C~old~
举一个具体的例子,一个 Raft 集群配置为 C~old~ [Server1、Server2 和 Server3],该集群的 Quorum 为(N/2)+1 = 2。现在,我们计划增加两个节点,新集群配置为 C~new~ [Server1、Server2、Server3、Server4、Server5],该集群的 Quorum 为(N/2)+1 = 3。由于提交日志是异步的,假设 Server1,Server2 比较迟钝,还在用老配置 C~old~,而 Server3,Server4,Server5 已“提交”新配置 C~new~
- 假设 Server5 触发选举,赢得 Server3,Server4,Server5 的投票(满足 C~new~ 的 3 Quorum 要求),成为 Leader;
- 假设 Server1 也触发选举,赢得 Server1,Server2 的投票(满足 C~old~ 的 2 Quorum 要求),成为 Leader。

Expand All @@ -28,7 +26,13 @@

最初,Diego Ongaro 在论文中提出了一种基于两阶段的联合共识(Joint Consensus)成员变更方法,但这种方式实现起来很复杂。后来,Diego Ongaro 又提出的一种更简单的方案 —— 单成员变更(Single Server Changes)。单成员变更的思路是,既然同时提交多个成员变更会存在问题,那每次就提交一个成员变更,如果要添加多个成员,那就执行多次单成员变更。

单节点变更的方法很容易穷举出所有情况,如图 6-22 所示,穷举集群奇/偶数节点下添加和删除情况。如果每次只操作一个节点,那么 **C~old~ 的 Quorum 和 C~new~ 的 Quorum 之间一定存在交集。也就是说,同一个 term 中,C~old~ 和 C~new~ 中交集的那个节点只会进行一次投票,要么投票给 C~old~,要么投票给 C~new~,这样就避免了同一 term 下出现两个 Leader**
单节点变更的方法很容易穷举出所有情况,如图 6-22 所示,穷举集群奇/偶数节点下添加和删除情况。如果每次只操作一个节点,那么 **C~old~ 的 Quorum 和 C~new~ 的 Quorum 之间一定存在交集**。同一个 term 中,C~old~ 和 C~new~ 中交集的那个节点只会进行一次投票,要么投票给 C~old~,要么投票给 C~new~,这样就避免了同一 term 下出现两个 Leader。


以图 6-22 第二种情况为例,C~old~[Server1、Server2、Server3],该集群的 Quorum 为(N/2)+1 = 2,C~new~[Server1、Server2、Server3、Server4],该集群的 Quorum 为(N/2)+1 = 3。假设 Server1、Server2 比较迟钝,还在用 C~old~ ,其他节点已经“提交”了 C~new~
- Server1 触发选举,赢得 Server1,Server2 的投票,满足 C~old~ Quorum 要求,当选 Leader;
- Server3 触发选举,赢得 Server3,Server4 的投票,但**不满足 C~new~ 的 Quorum 要求,选举失效**


:::center
![](../assets/raft-single-server.svg) <br/>
Expand Down
31 changes: 14 additions & 17 deletions consensus/raft-leader-election.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# 6.4.1 领导者选举

Raft 是一个强领导者算法。

Raft 算法中,节点有三种角色,并且可以互相转换:

- **领导者(Leader)**:接收 client(客户端)的所有请求,Raft 算法中所有的操作以 Leader 为准。Leader 平常的工作包括 3 个部分:处理写请求、管理日志复制、不断发送心跳信息通知其他节点”我是 Leader,我还活者,你们现在不要发起新的选举“;
Expand All @@ -8,24 +10,27 @@ Raft 算法中,节点有三种角色,并且可以互相转换:



Raft 将整个系统的时间划分为一个个独立的阶段,
Raft 将整个系统的时间划分为一个个独立的“任期”(term)。每个 term 由单调递增的数字(任期编号)标识**

- 任期越大,话语权越大:本地任期较小的总是服从任期更好的消息来源。
- 每次选举,任期都会 +1:确保不会在多个选举过程中计票混乱。
- 一山不容二虎:同一个任期内只能选择出一个 Leader。
- 高任期的节点收到低任期节点的任何请求时,会直接拒绝。

节点进行“交流”(RPC 通信)时,任期是第一优先级的,只有对齐了任期,才有谈其他的基础。

简单来说,任期标明了 Leader 的服役阶段。保证在某些极端的情况下最终只有一个 Leader,例如下面两种情况:


简单来说,任期标明了 Leader 的服役阶段。

:::center
![](../assets/raft-term.svg)
图 6-15 Raft term 与成员状态变更
:::

- **选举出现平票**:假如有 2 个节点 A 和 B,它们的 term 都为 1。当 Leader 宕机后这两个节点转变为 Candidate 开始选举,但在选举阶段它们都没有达到大多数同意,这时节点 A 先发生**随机时间**超时,节点 A 把它的任期加 1,重新开始新的选举。由于**各个节点都会无条件优先接受比自己任期更大的请求**,所以,下一轮选举时,节点 A 肯定会得到大多数同意,成为 Leader。
- **集群出现脑裂**:当 Leader 宕机后或者网络分区故障时,由于联系不上 Leader,Follower 会转变成 Candidate,把自己的 term 加 1,并选举成为新的 Leader,**选举出来的新集群具有更大的 term**。当之前宕机的 Leader 恢复或网络分区恢复后,旧的 Leader 虽然在运行,但它的 term 已经不足以形成多数派,一旦旧 Leader 发现有更大的 term 时,就会放弃自己 Leader 的角色转换为 Follower。

每个 Follower 在本地维持一个选举时钟,选举时钟到期时,如果没有收到 Leader 的日志或者心跳,那么就开始发起选举。

每个 Follower 在本地维持一个选举计时器,选举计时器到期前,如果没有收到 Leader 的日志或者心跳,那么就开始发起选举。Follower 向所有的节点发送投票消息(RequestVote RPC)结构如下
投票消息(RequestVote RPC)的结构大致如下

```json
{
Expand All @@ -38,9 +43,9 @@ Raft 将整个系统的时间划分为一个个独立的阶段,

图 6-16 概述了 Raft 集群 Leader 选举过程。会发生下面的情况:

- **选举超时**发出的投票请求在固定时间内没有收到其他节点的响应,或者是收到响应(或者同意投票)的节点数量没有达到 N/2+1,那么选取超时进入下一轮选举。
- **选举成功**如果选举过程中收到大于N/2+1数量的节点的投票,那么选举成功,当前的节点成为新的 Leader
- **选举失败**如果选举过程中收到来及其他节点的 Leader 心跳,或者是请求投票响应的 Term 大于当前的节点 Term,那么说明有新任期的 Leader,将转变为 Follower
- **选举超时**在固定时间内未收到其他节点的响应,或者收到的响应(同意票)的节点数量未达到 Quorum N/2+1 的要求。此时,触发选举超时进入下一轮选举;
- **选举成功**选举过程中,收到的响应节点的数量达到 Quorum 要求,选举成功,该节点成为集群的 Leader
- **选举失败**选举过程中,收到 Leader 心跳,或者发现有更高的 term,说明有新任期的 Leader,结束结束当前的选举


:::center
Expand All @@ -51,14 +56,6 @@ Raft 将整个系统的时间划分为一个个独立的阶段,



Raft 算法中还有个很重要的概念 —— term,**Raft 将时间分割为不同长度,称为 Leader 的 term(任期)。每个 term 由单调递增的数字(任期编号)标识**。任期一般包含两阶段:第一阶段是选举阶段,第二阶段为已选举出领导者的阶段。但任期也可能只包含选举阶段(并没有成功选举出 Leader )。如图 6-15 所示,term 1 开始一次新选举,这次选举成功并开始正常操作,term 2 同样如此,但 term 3 选举失败,进入 term 4。



term 在 Raft 中起到了逻辑时钟的作用,可用于保证在某些极端的情况下最终只有一个 Leader,例如下面两种情况:






Expand Down
5 changes: 4 additions & 1 deletion consensus/raft-log-replication.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# 6.4.2 日志复制


在 Raft 系统中,所有的数据变化都是以日志记录的形式添加到服务节点之中。服务节点会不断的读取日志记录,并将日志记录更新到服务节点的数据中。日志记录最开始的状态是 uncommited, 更新之后状态则变为 commited。commited 意味着:日志记录不会被回滚,可以安全地应用到状态机。


前面的介绍中,笔者已经阐述过:Raft 的本质就是多个副本的日志数据达成一致的解决方案。

理解日志复制的问题之前,我们得先搞清楚 Raft 中的日志和日志项是什么。
Expand All @@ -16,7 +20,6 @@
:::



## 1. 日志复制

Raft 是强 Leader 模型的算法,日志项只能由 Leader 复制给其他成员,这意味着日志复制是单向的,Leader 从来不会覆盖本地的日志项,即所有的日志项以 Leader 为准。
Expand Down
14 changes: 7 additions & 7 deletions network/virtual-nic.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# 3.5.3 虚拟网卡 veth
# 3.5.3 虚拟网卡 Veth

Linux 内核 2.6 版本支持网络命名空间的同时,也提供了专门的虚拟网卡 veth(Virtual Ethernet,虚拟以太网网卡)。
Linux 内核 2.6 版本支持网络命名空间的同时,也提供了专门的虚拟网卡 Veth(Virtual Ethernet,虚拟以太网网卡)。

veth 实现原理的本质是一种“反转数据传输方向”的实现,即:在内核中将需要被发送的数据包“反转"为新接收到的数据包,重新进入内核网络协议栈中处理。通俗一点的解释:veth 就是带着两个“水晶头”的一根“网线”,从网线的一头发送数据,另一头就会收到数据。因此,Veth 也被说成是一对设备(称作 veth-pair)。
Veth 实现原理的本质是一种“反转数据传输方向”的实现,即:在内核中将需要被发送的数据包“反转"为新接收到的数据包,重新进入内核网络协议栈中处理。通俗一点的解释:Veth 就是带着两个“水晶头”的一根“网线”,从网线的一头发送数据,另一头就会收到数据。因此,Veth 也被说成是“一对设备”(Veth-Pair)。

veth 的典型应用是连接各类虚拟设备,让原本隔离的网络名称空间可以互相通信。当我们创建一个 veth 设备时,会自动创建另一个关联的 veth 设备(网线的另一头)。将关联的 veth 设备其移动到其他网络命名空间后,两个 veth 设备之间的数据包传输被视为在一个以太网连接上传输。
Veth 的典型应用是连接各类虚拟设备,让原本隔离的网络名称空间可以互相通信。当我们创建一个 Veth 设备时,会自动创建另一个关联的 Veth 设备(网线的另一头)。将关联的 Veth 设备其移动到其他网络命名空间后,两个 Veth 设备之间的数据包传输被视为在一个以太网连接上传输。

假设我们已经有两个相互隔离的网络命名空间 ns1 和 ns2,它们的网络拓扑结构如图 3-14。下面笔者进行操作演示,帮助你理解 veth 设备如何实现网络命名空间的互通。
假设我们已经有两个相互隔离的网络命名空间 ns1 和 ns2,它们的网络拓扑结构如图 3-14。下面笔者进行操作演示,帮助你理解 Veth 设备如何实现网络命名空间的互通。

:::center
![](../assets/linux-veth.svg)<br/>
Expand All @@ -26,7 +26,7 @@ $ ip link set veth1 netns ns1
$ ip link set veth2 netns ns2
```

veth 是虚拟的网络设备,因此具备虚拟网卡的特征。即可配置 IP/MAC 地址。接下来,给 veth 设备配置上 ip 地址,它们的 IP 地址处于同一个子网 172.16.0.1/24 中,同时激活 veth 设备。
Veth 是虚拟的网络设备,因此具备虚拟网卡的特征。即可配置 IP/MAC 地址。接下来,给 Veth 设备配置上 ip 地址,它们的 IP 地址处于同一个子网 172.16.0.1/24 中,同时激活 Veth 设备。

```bash
# 配置命名空间1
Expand All @@ -51,7 +51,7 @@ PING 172.16.0.2 (172.16.0.2) 56(84) bytes of data.
64 bytes from 172.16.0.2: icmp_seq=2 ttl=64 time=0.063 ms
```

虽然 veth 设备模拟网卡直连的方式解决了两个容器之间的通信问题,但面对多个容器间通信需求,如果只用 Veth 设备的话,事情就会变得非常麻烦。让每个容器都为与它通信的其他容器建立一对专用的 veth 设备,根本不切实际。
虽然 Veth 设备模拟网卡直连的方式解决了两个容器之间的通信问题,但面对多个容器间通信需求,如果只用 Veth 设备的话,事情就会变得非常麻烦。让每个容器都为与它通信的其他容器建立一对专用的 Veth 设备,根本不切实际。


此时,就迫切需要一台虚拟化交换机来解决多容器之间的通信问题,这正是笔者前面多次提到的 Linux bridge。
Expand Down
4 changes: 1 addition & 3 deletions network/vxlan.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ VXLAN 属于 NVO3(Network Virtualization over Layer 3,三层虚拟化网络

在 VXLAN 隧道网络中,负责“封装/解封”的设备称为“VTEP 设备”(VXLAN Tunnel Endpoints,VXLAN 隧道端点),它在 Linux 系统中实际上是一个虚拟 VXLAN 网络接口。当源服务器内的容器发出原始数据帧后,首先在隧道的起点(VTEP 设备)被封装成 VXLAN 格式的报文,然后被主机 IP 网络传递到隧道的终点(也就是目标服务器中的 VTEP 设备)。目标服务器内的 VETP 设备解封 VXLAN 报文,得到原始的数据帧,转发至目标服务器内的某容器。

从 Linux 内核 3.12 版本起,Linux 内核对 VXLAN 技术有了完备的支持。只要三层可达的网络,不需要专门的硬件,简单的配置下,就可以部署基于 VXLAN 的隧道网络。

用一个具体的例子解释,下面的命令演示了如何在 Linux 系统中配置 VXLAN 接口并将其绑定到 Linux bridge。
Linux 内核 3.12 版本起,开始支持完备的 VXLAN 技术(多播模式、单播模式、IPv6 支持等)。只要三层可达的网络,不需要专门的硬件,简单的配置下 Linux 系统,就可以部署 VXLAN 的隧道网络。举一个具体的例子,下面的命令演示了如何在 Linux 系统中配置 VXLAN 接口并将其绑定到 Linux bridge。

```bash
# 创建一个 bridge
Expand Down

0 comments on commit 9a7391e

Please sign in to comment.