Skip to content

Commit 051c45e

Browse files
committed
Refactor: explain algo to determine apply order without SCC in mmp3
1 parent b44bbde commit 051c45e

2 files changed

Lines changed: 49 additions & 27 deletions

File tree

_posts/2021-06-14-mmp3.md

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ excerpt: "小孩子才选master, 成年人只用multi-master"
4949
- 任一节点都可写,
5050
- 任一笔写入都可以严格在1个 RTT 内完成.
5151

52-
这就是今天要介绍的
52+
这就是今天要介绍的
5353
[200行代码实现paxos-kv](https://zhuanlan.zhihu.com/p/275710507)
5454
的改进版: mmp-3: multi-master-paxos 3副本实现.
5555

@@ -122,11 +122,11 @@ replica-0 上的 proposer P0, 顺次完成 phase-1, phase-2 和 commit:
122122

123123
因为 proposer 本身只是一个数据结构, 在 paxos 中, 它不需要跟 acceptor 有什么绑定关系,
124124
所以, 我们可以**让 proposer 运行在任何一个 replica 上**:
125-
把 proposer 发到另一个 replica 上运行,
125+
把 proposer 发到另一个 replica 上运行,
126126
这样消息的传输就可以转变成 proposer 的传输.
127127

128128
要达到 paxos 要求的 2/3的多数派,
129-
也只需要将 proposer 发到另外一个 replica,
129+
也只需要将 proposer 发到另外一个 replica,
130130
因为这个 proposer 永远只有1个实例, 所以不会出现不一致(proposer 或者在R0上工作或者在在R1上工作).
131131

132132
> 如果要将 proposer 发到 2个 replica 就会复杂一些, 例如5节点中 quorum=3, 2个不同的 proposer
@@ -241,7 +241,7 @@ message Ins {
241241
![](/post-res/mmp3/digraphseensize=55dpi=100layout=-f7876b9a4c1e4ba8.jpg)
242242

243243
> classic-paxos 中要求 prepare 阶段看到的已存在的值要使用,
244-
> 而 mmp3 中将所有 prepare 阶段看到的 `Deps` 的值做了并集,
244+
> 而 mmp3 中将所有 prepare 阶段看到的 `Deps` 的值做了并集,
245245
> 实际上并没有破坏 paxos 的约束,
246246
> 只不过 classic-paxos 假设它的****是任意的, 不一定可取并集,
247247
> mmp3 中可以把 prepare 过程中看到的 `Deps` 的值认为是 `VBal` 为 0 的一个值,
@@ -322,7 +322,7 @@ interfering 的 instance 的冲突带来的另一个RTT开销.
322322
那么 `B.Deps`, 也就是 B 看到的所有其他 instance 的 id 集合, 就已经复制到了某个 quorum.
323323
那么 A 在运行 paxos 的时候,一定会看到 B commit 的 `B.Deps` 的值.
324324

325-
又因为 `A.Deps` 是2个在 prepare 阶段看到的 `Deps`的值的并集,
325+
又因为 `A.Deps` 是2个在 prepare 阶段看到的 `Deps`的值的并集,
326326
因此 `A.Deps` 一定包含全部 `B.Deps` 的instance.
327327

328328
于是实现 apply 算法的思路就是:
@@ -349,20 +349,31 @@ interfering 的 instance 的冲突带来的另一个RTT开销.
349349

350350
## Lemma-2: 不需要 SCC
351351

352-
第2个小结论:
352+
我们不需要遍历出所有的 Strongly-Connected-Component(SCC),
353+
就可以确定 Apply 的顺序.
353354

354-
**如果 A, B不属于同一个 SCC, 即, A ∈ SCC₁ B ∉ SCC₁, 那么**:
355+
我们的第2个小结论是:
356+
357+
**如果 A, B不属于同一个 SCC, 即, A ∈ SCC₁ 且 B ∉ SCC₁,
358+
那么一定有且只有下面其中一种情况成立**:
355359

356360
- **A → B ⇒ A.Deps ⊃ B.Deps**.
357361
- **B → A ⇒ B.Deps ⊃ A.Deps**.
358362

359-
因为根据 Lemma-0,
360-
任意2个 instance 至少有一个依赖关系,
361-
如果X ∈ B.Deps 且 X ∉ A.Deps,
362-
那么必然有 X → A, 导致 A → B → X → A 成为一个SCC.
363+
即, 如果 A 依赖 B, 则 A 的依赖集合一定是 B 的依赖集合的超集.
364+
365+
简单的证明如下:
366+
367+
以 A → B 的情况举例,
368+
假设有一个 X 在 B 的依赖集里但不在A的依赖集里, 即: X ∈ B.Deps 且 X ∉ A.Deps,
369+
那么根据 Lemma-0(任意2个 instance 至少有一个依赖关系),
370+
必然有 X → A, 导致 A → B → X → A 成为一个 SCC, 这跟假设矛盾.
371+
372+
QED
363373

364-
因此, **不论A, B是否在一个 SCC 中, 保证 Linearizability
365-
的条件都可以用 Deps 来确定,
374+
因此, **不论 A, B 是否在一个 SCC 中, 保证 Linearizability
375+
的条件都可以用 Deps 来确定,
376+
即只需保证 Deps 的子集关系决定 Apply 的先后关系集合.
366377
所以我们的算法不必寻找 SCC , 只需遍历依赖关系**.
367378

368379
## 减小遍历数量: 只需考虑最老的 instance

_src/mmp3/2021-06-14-mmp3.md

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ excerpt: "小孩子才选master, 成年人只用multi-master"
4848
- 任一节点都可写,
4949
- 任一笔写入都可以严格在1个 RTT 内完成.
5050

51-
这就是今天要介绍的
51+
这就是今天要介绍的
5252
[200行代码实现paxos-kv][post-paxoskv]
5353
的改进版: mmp-3: multi-master-paxos 3副本实现.
5454

@@ -145,11 +145,11 @@ sequenceDiagram
145145

146146
因为 proposer 本身只是一个数据结构, 在 paxos 中, 它不需要跟 acceptor 有什么绑定关系,
147147
所以, 我们可以**让 proposer 运行在任何一个 replica 上**:
148-
把 proposer 发到另一个 replica 上运行,
148+
把 proposer 发到另一个 replica 上运行,
149149
这样消息的传输就可以转变成 proposer 的传输.
150150

151151
要达到 paxos 要求的 2/3的多数派,
152-
也只需要将 proposer 发到另外一个 replica,
152+
也只需要将 proposer 发到另外一个 replica,
153153
因为这个 proposer 永远只有1个实例, 所以不会出现不一致(proposer 或者在R0上工作或者在在R1上工作).
154154

155155
> 如果要将 proposer 发到 2个 replica 就会复杂一些, 例如5节点中 quorum=3, 2个不同的 proposer
@@ -524,7 +524,7 @@ digraph seen
524524
```
525525

526526
> classic-paxos 中要求 prepare 阶段看到的已存在的值要使用,
527-
> 而 mmp3 中将所有 prepare 阶段看到的 `Deps` 的值做了并集,
527+
> 而 mmp3 中将所有 prepare 阶段看到的 `Deps` 的值做了并集,
528528
> 实际上并没有破坏 paxos 的约束,
529529
> 只不过 classic-paxos 假设它的****是任意的, 不一定可取并集,
530530
> mmp3 中可以把 prepare 过程中看到的 `Deps` 的值认为是 `VBal` 为 0 的一个值,
@@ -586,7 +586,7 @@ interfering 的 instance 的冲突带来的另一个RTT开销.
586586
> - R1 send b1 to R0, b1.Deps = [1, 1, 0]
587587
> - R0 commit a1
588588
> - R1 commit b1
589-
>
589+
>
590590
> 这样 a1 ∈ b1.Deps 且 b1 ∈ a1.Deps
591591
592592
依赖关系很直观, 这个依赖关系的图中,
@@ -603,7 +603,7 @@ interfering 的 instance 的冲突带来的另一个RTT开销.
603603
那么 `B.Deps`, 也就是 B 看到的所有其他 instance 的 id 集合, 就已经复制到了某个 quorum.
604604
那么 A 在运行 paxos 的时候,一定会看到 B commit 的 `B.Deps` 的值.
605605

606-
又因为 `A.Deps` 是2个在 prepare 阶段看到的 `Deps`的值的并集,
606+
又因为 `A.Deps` 是2个在 prepare 阶段看到的 `Deps`的值的并集,
607607
因此 `A.Deps` 一定包含全部 `B.Deps` 的instance.
608608

609609

@@ -632,19 +632,30 @@ interfering 的 instance 的冲突带来的另一个RTT开销.
632632

633633
## Lemma-2: 不需要 SCC
634634

635-
第2个小结论:
635+
我们不需要遍历出所有的 Strongly-Connected-Component(SCC),
636+
就可以确定 Apply 的顺序.
637+
638+
我们的第2个小结论是:
636639

637-
**如果 A, B不属于同一个 SCC, 即, A ∈ SCC₁ B ∉ SCC₁, 那么**:
640+
**如果 A, B不属于同一个 SCC, 即, A ∈ SCC₁ 且 B ∉ SCC₁,
641+
那么一定有且只有下面其中一种情况成立**:
638642
- **A → B ⇒ A.Deps ⊃ B.Deps**.
639643
- **B → A ⇒ B.Deps ⊃ A.Deps**.
640644

641-
因为根据 Lemma-0,
642-
任意2个 instance 至少有一个依赖关系,
643-
如果X ∈ B.Deps 且 X ∉ A.Deps,
644-
那么必然有 X → A, 导致 A → B → X → A 成为一个SCC.
645+
即, 如果 A 依赖 B, 则 A 的依赖集合一定是 B 的依赖集合的超集.
646+
647+
简单的证明如下:
648+
649+
以 A → B 的情况举例,
650+
假设有一个 X 在 B 的依赖集里但不在A的依赖集里, 即: X ∈ B.Deps 且 X ∉ A.Deps,
651+
那么根据 Lemma-0(任意2个 instance 至少有一个依赖关系),
652+
必然有 X → A, 导致 A → B → X → A 成为一个 SCC, 这跟假设矛盾.
653+
654+
QED
645655

646-
因此, **不论A, B是否在一个 SCC 中, 保证 Linearizability
647-
的条件都可以用 Deps 来确定,
656+
因此, **不论 A, B 是否在一个 SCC 中, 保证 Linearizability
657+
的条件都可以用 Deps 来确定,
658+
即只需保证 Deps 的子集关系决定 Apply 的先后关系集合.
648659
所以我们的算法不必寻找 SCC , 只需遍历依赖关系**.
649660

650661

0 commit comments

Comments
 (0)