Raft以多数派机制化解2PC阻塞 确立分布式共识标准

[Chinese] Chapter 11: consistency and consensus — Scott Shi

Scott Shi

保持线性一致性的代价直接受制于网络延迟,传统两阶段提交因协调者单点故障易致系统死锁,工程落地须依托Raft等共识算法由存活多数派自动推进决议。

AI-assisted summary of [Chinese] Chapter 11: consistency and consensus — original source. Check the original for full context.

Source published:

Key ideas

  • 线性一致性(Linearizability)本质上是针对外部观察者的最新性保证(Recency guarantee),在数学等价上与全序广播及分布式共识互为充要映射,且其时间开销与网络延迟严格成正比。 (20:00)
  • CAP 定理常被误解为三选二,但在真实的分布式环境中网络分区是无法消除的物理现实,实际权衡核心在于网络分区发生时选择牺牲线性一致性还是可用性。 (25:00)
  • 两阶段提交(2PC)因协调者单点故障与阻塞机制会导致系统吞吐出现数量级暴跌(如从单机十万级跌至百级),且单主复制与 2PC 均无法保证共识所需的终止性(Termination)。 (60:00)
  • Raft 算法通过拆分角色与任期机制降低了 Paxos 的工程实现复杂度,但受限于 FLP 不可能性定理,异步网络中不存在绝对能收敛的确定性共识算法,工程上依赖随机化超时破局。 (71:45)

Detailed notes

## Background 本内容由 Scott Shi 于 2021 年 1 月 20 日发布在 YouTube 平台(实际录制于 2020 年 8 月 27 日)。视频聚焦于经典分布式系统著作第 11 章“一致性与共识(Consistency and Consensus)”的技术导读,并随附了讲者配套制作的详细演示文稿文档。

## TL;DR 本次分享全面剖析了分布式系统领域最核心也最复杂的一致性与共识机制。讲者深入辨析了线性一致性与可串行化的边界,剖析了 CAP 定理下网络分区的必然性,并梳理了全序、偏序以及兰伯特逻辑时钟的适用场景与局限。随后,内容以生动的“教堂婚礼”比喻剖析了两阶段提交(2PC)的阻塞瓶颈,系统阐释了共识算法的四大核心属性,并对比了 Paxos 与 Raft 的设计演进及 FLP 不可能性定理。最后,讲座就 Gossip 协议与共识的区别、2PC 故障恢复路径以及线性一致性的外部观察等实际疑问进行了深入解答。

## Atmosphere & style 整场讲座兼具硬核理论推导与工程师技术沙龙的真实松弛感。讲者开场带着对杂音麦克风的调侃自嘲破冰,随后迅速切入高维抽象的分布式概念,巧妙穿插“猴子敲打字机”与“牧师主持婚礼”等绝妙比喻化繁为简。讲述过程既充满对 Twitter 生产事故与极端竞态的敬畏与敏锐直觉,又透露出备课极度烧脑后的坦诚疲态,听感极其扎实生动且富有启发性。

## Bulletin - [20:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1200s) 线性一致性(Linearizability)本质上是针对外部观察者的最新性保证(Recency guarantee),在数学等价上与全序广播及分布式共识互为充要映射,且其时间开销与网络延迟严格成正比。 - [25:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1500s) CAP 定理常被误解为三选二,但在真实的分布式环境中网络分区是无法消除的物理现实,实际权衡核心在于网络分区发生时选择牺牲线性一致性还是可用性。 - [01:00:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=3600s) 两阶段提交(2PC)因协调者单点故障与阻塞机制会导致系统吞吐出现数量级暴跌(如从单机十万级跌至百级),且单主复制与 2PC 均无法保证共识所需的终止性(Termination)。 - [01:11:45](https://www.youtube.com/watch?v=gaogvQVJVxw&t=4305s) Raft 算法通过拆分角色与任期机制降低了 Paxos 的工程实现复杂度,但受限于 FLP 不可能性定理,异步网络中不存在绝对能收敛的确定性共识算法,工程上依赖随机化超时破局。

## Key takeaways - [00:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=0s) 计算机领域存在两种一致性:业务层面的 ACID 语义一致性与分布式系统中处理副本冗余的共识一致性,后者旨在将多节点系统抽象为单台最新即时可见的单机数据库。 - [05:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=300s) 线性一致性与事务可串行化互不包含;SSI 满足可串行化但可能读取历史快照违背线性一致,而单对象最新读写满足线性一致却缺乏跨对象事务的原子性与隔离性。 - [10:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=600s) 判定线性一致性的准则在于能否在每个读写操作的发起与返回窗口之间找到一个原子切入点,投影到单机时间轴且不发生因果时序矛盾。 - [15:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=900s) 只有在某个读操作完全结束后,后续严格晚于该时刻发起的读操作读到旧值,才构成确凿的线性一致性破坏;若时间窗口存在重叠则仍可解释为合法串行。 - [20:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1200s) 无主复制架构(如 Dynamo)由于极端边界竞态条件难以给出严格的线性一致性形式化证明,工业界生产实践中存在偶发异常与状态丢失隐患。 - [25:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1500s) 在共识理论与外部观察者视角下,无限延迟、节点崩溃与网络分区在黑盒表现上是等价的,对半精准切分的分区易引发无多数派与脑裂风险。 - [30:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1800s) 主从复制中 Master 宕机若选择 Failover 会面临数据丢失或高延迟权衡,而 Kafka 等系统通过放弃昂贵的强一致与事务语义换取流式架构的极致吞吐。 - [35:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=2100s) 偏序(如 Git 分支)构成了 DAG 结构,而全序(如单向链表)代价高昂;若并发操作互不冲突,系统只需满足因果序而无需强求全局全序。 - [40:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=2400s) Lamport 逻辑时间戳通过二元组保证了因果一致性,但由于其本质是后验审计机制,无法在事件发生当时实时决策并发互斥或达成线性一致。 - [45:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=2700s) 全序广播要求可靠交付(Reliable Delivery)与全局全序(Total Order),其理论语义与线性一致性、分布式共识相互等价。 - [55:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=3300s) 两阶段提交(2PC)中协调者将决策刷盘的一瞬间为不可逆的原子提交点;若协调者此时宕机,参与者将陷入无限期挂起并锁死数据行。 - [01:00:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=3600s) 合格的分布式共识算法必须同时满足一致同意(Agreement)、完整性(Integrity)、有效性(Validity)与终止性(Termination),单主复制正是因为无法自发保证 Termination 而不是严格的共识协议。 - [01:08:30](https://www.youtube.com/watch?v=gaogvQVJVxw&t=4110s) Raft 将节点角色清晰拆分为 Leader、Follower 与 Candidate,其心跳周期应比选举超时小一个数量级,以平衡网络抖动引发的误判与故障感知敏捷度。 - [01:11:45](https://www.youtube.com/watch?v=gaogvQVJVxw&t=4305s) FLP 不可能性定理指出异步网络模型下哪怕仅单节点崩溃也无法保证确定性算法必然达成共识,工程实践依赖随机化超时机制避免活锁。 - [01:17:15](https://www.youtube.com/watch?v=gaogvQVJVxw&t=4635s) Gossip 协议本质是一种降低单节点网络负载的异步广播与最终一致性模式,与追求强一致、确定性裁决和毫秒级判定的 Raft/Paxos 有本质不同。 - [01:24:45](https://www.youtube.com/watch?v=gaogvQVJVxw&t=5085s) 在 2PC 恢复机制中,Prepare 阶段超时直接 Abort,而 Commit 决策一旦刷盘,协调者必须持续重试重连直至故障参与者复活确认。

## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=0s) 麦克风杂音、两种一致性与线性一致性(Linearizability)的引入

讲座开场时发生了一段小插曲,讲者反复调试设备,自嘲之前几天开会时说了半天别人根本听不见,看着麦克风长得很高级很漂亮,实际收音效果却相当糟糕。在确认大家能正常听到后,内容正式进入第11章的核心——一致性(Consistency)与共识(Consensus)。

讲者首先厘清了计算机领域中常被混淆的“两种一致性”: 1. **数据库层面的语义一致性(Database Consistency)**:例如 ACID 里的 C。它是业务层面的逻辑约束,比如系统中规定某段时间必须有且仅有两个值班人员(On-call),这完全依赖客户端编写的应用逻辑,底层数据库引擎本身并不关心这类业务现实。 2. **共识与分布式系统的一致性(Consensus / Distributed System Consistency)**:这是本讲的核心。由于分布式系统为了保证高可用与持久性(Durability)进行数据冗余备份(Data Replication),确保挂掉一个数据中心时还能从其他节点读取数据,这就不可避免地会引入副本间的状态不一致。即使使用同步复制(Synchronous Replication),提交的数据(Committed data)一致了,未提交的数据(Uncommitted data)在各副本之间依然处于不一致状态。因此在分布式环境下,副本间的不一致性是必然存在的物理现实。

为了驾驭这种复杂性,分布式系统提出了最基础也最核心的目标:**把复杂的分布式多节点系统抽象得像一台单机数据库一样简单**。无论后端采用了主从复制(Master/Slave、Primary/Secondary)还是主主复制(Master/Master),从客户端的视角来看,所有操作就像是在和一个单独的数据库实例交互。这个能够提供“最新写入即时可见”的强一致性抽象,其正式定义即为**线性一致性(Linearizability)**。

---

[05:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=300s) 线性一致性与可串行化之辨、诡异的生产 Bug 与灵感想象力

概念辨析上,线性一致性(Linearizability)与事务隔离级别里的可串行化(Serializability)绝非同一概念,二者互不包含: - **满足可串行化,但不满足线性一致性**:最典型的例子是可串行化快照隔离(Serializable Snapshot Isolation, SSI)。它保证了事务之间执行效果等价于某种串行顺序,但是在一个较长事务运行期间,读操作读取的是快照历史数据(Stale data),而非系统刚刚写下去的最新数据,因此违反了线性一致性。 - **满足线性一致性,但不满足可串行化**:例如在同时写入多个对象时,对单个对象上的读写严格满足单点最新(满足线性一致性),但跨对象的整体多写操作可能缺乏原子性(Atomicity)与隔离性,无法保证“要么全成要么全败”,也无法保证全局的串行执行顺序。

讲者坦言,这类深层理论在普通面试中很少被问及,但对于设计非玩具性质、不允许丢数据的核心数据库系统而言,是不可或缺的底层直觉。此外,深厚的理论能帮助工程师排查现实中极其离奇的“灵异现象”: - **文件描述符泄漏怪事**:讲者提到自己妻子最近上线部署代码,运行在 Redshift 相关调用上,调用频率极低,但每半小时文件描述符(File Descriptor)就会泄漏两三千个,监控曲线直往上蹿。反复审查配置毫无破绽,由于服务使用 Scala 编写,怀疑是 JVM 编译底层某些 Lazy class load 逻辑暗中打开了资源未关闭,排查极为棘手。 - **Twitter 著名的“Skewed TTL”事故**:大约在 2013 或 2014 年,Twitter 线上遭遇重大故障,洛杉矶湖人队(LA Lakers)的主页与品牌页面突然全部返回 404(Page Not Found)。经复盘,Twitter 曾对湖人队等热门主页设置了缓存,某次缓存过期后回源去数据库读取,由于未知竞态,竟然读出了一个空值(Null value),并且程序为这个 Null 值固化了 12 小时的 TTL 缓存。导致在整整 12 个小时内,全网访问湖人队主页全部报错,直到 12 小时后缓存失效重新回源才恢复。公司耗费大量人力做事故复盘(Post-mortem analysis),仍旧无法完全解释为何当时那次读会拿到 Null。

在复杂的分布式现实中,“你真的不知道怎么解释的时候,需要你比较有想象力”。分布式并发场景下理论上可能触发的极端竞态,只要运行规模足够大、时间足够长,就必然发生。

---

[10:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=600s) 读写时序与 CAS 操作:如何判定是否满足线性一致性

为了直观判定系统是否满足线性一致性,必须在时间轴上分析操作的并发窗口与重叠关系。在此以 CAS(Compare-And-Set)原子操作及读写操作为例:

```mermaid flowchart TD accTitle: 线性一致性判定逻辑 accDescr: 展示将各客户端的并发读写映射到单一时间轴并判定是否满足线性一致性的流程。

subgraph Operations ["客户端并发操作 (Client Operations)"] D_Write["Client D: 写 X=0"] A_Write["Client A: 写 X=1"] B_Ops["Client B: 读 X=1 -> CAS(X, 1, 2) -> 读 X=2"] C_Ops["Client C: 读 X=1 -> 读 X=2 -> CAS(X, 2, 4)"] end

subgraph LinearCheck ["线性一致性有效性投影"] Project{"能否在物理真实耗时窗口内<br/>为每次操作找到一个瞬间点<br/>投影到单一虚拟时间轴?"} Valid["满足线性一致性 (Valid Linearizability):<br/>读操作符合最新写入结果"] Invalid["违反线性一致性 (Violation):<br/>在读到最新值后,后续读又读回旧值 (如读到 4 之后又读到 2)"] end

Operations --> Project Project -- "存在合法时序解释" --> Valid Project -- "不可逆的时序倒退" --> Invalid ```

讲者结合示例图详细剖析了不同客户端(Client A、B、C、D)交错执行的场景: - **Client D**:发起写操作设置 $X=0$,随后尝试通过 CAS 比较 $X$ 是否为 0 并置为 3,但此时 $X$ 已经被并发修改,因此 CAS 失败。 - **Client A**:将 $X$ 写为 1,随后读取 $X$,读到最新值 4。 - **Client B 与 C**:Client B 读到 $X=1$,执行 CAS 将 $X$ 从 1 改为 2 并成功,接着读取 $X$ 返回 2;Client C 读到 $X=1$,随后读到 2,紧接着 CAS 将 $X$ 从 2 改为 4 并返回 OK。

对于并发交错,关键在于理解**原子操作点(Atomic operation point)**与**网络耗时窗口**: - 一个操作并不是瞬间完成的,它从发起(Request)到收到返回(Response)存在一个物理时间窗口。在这个窗口内,真实的生效点可能发生在任意微时刻。 - **早写后返现象**:Client D 发起写 $X=0$,但网络延迟导致“返回 OK”很晚才到达;在它尚未返回前,Client A 已经发起了写 $X=1$,且 Client B 发起读操作并读到了 $X=1$。尽管从绝对发起的物理时刻看 Client B 读开始得很早,但它的生效时刻发生在 $X=1$ 写入之后,这完全是合法的,并不违反线性一致性。 - **投影原则**:只要能够找到一种合理的假想时序,把所有客户端的读写操作在它们各自的发起与返回窗口之间找到一个切入点,**投影(Project)到同一个单机时间轴上并且不产生时序矛盾**,那么该系统就是满足线性一致性的。

---

[15:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=900s) 违规案例分析、随机漫步与莎士比亚定理

什么情况下会彻底破坏线性一致性? - **时间倒流(Revert back)**:如果数据已经被修改为 $X=2$,之后某个严格晚于该时刻的读操作却读回了 $X=0$,那么系统就违反了线性一致性。 - **严格先后关系被打破**:如果 Client 已经在某个时间点读到了 $X=4$(此时 $X=4$ 的写操作已经完全结束并返回),而紧随其后另一个读操作发起的时刻**严格晚于(Strictly after)**读到 4 的时刻,它却读回了旧值 $X=2$。在单一时间轴上,由于 $X$ 已经由 2 跃变为 4 且已对外界确认,后续绝不可能在没有写回操作的情况下凭空再读到 2。这种时序违规就是铁证般的“Violation”。 - **重叠窗口的挽救可能**:如果读到 2 的那个操作它的执行区间足够长,其发起的起始点可以向前拖动,与写入 4 的过程有交集,那么在理论投影上就可以解释为“该读操作的实际生效时刻发生在变为 4 之前”,此时便不构成违反。然而一旦两个时间区间在物理上完全断开、呈现出 Strict After 关系,就绝无狡辩的余地。

讲者由此强调,线性一致性本质上就是**最新性保证(Recency guarantee)**。在分布式系统分析中,有两个极富哲学意味的数学定理可以作为类比: - **无限猴子打字机定理(莎士比亚作品)**:让计算机无休止地随机输出字符,只要给予足够长的时间,它纯凭概率也必然能完整打印出莎士比亚的全套作品。 - **二维平面随机漫步(Random Walk)**:数学证明,在二维平面上进行随机漫步的人,只要时间足够长,其返回原点的概率是 100%;但在三维空间(3D)中允许上下前后左右自由漫步时,就无法保证必定能回到原点。 在分布式并发环境中,只要理论逻辑上存在某种并发竞态的可能性,系统运行次数足够多、时间足够久,这个理论边界 Case 就必然会发生。现实中之所以能读到旧值 2,极大概率是因为底层是多个副本构成的集群,客户端读取时命中了尚未同步最新修改的跟随者副本(Replica)。

---

[20:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1200s) 复制架构下的线性一致性、Dynamo 争议与 CAP 真实含义

讲者分析了各类常见复制架构在面对线性一致性时的表现:

| 复制架构类型 | 是否满足线性一致性 | 机制与关键考量 | |:--- |:--- |:--- | | **单主复制 (Single-Leader Replication)** | 潜在满足 (Potentially Yes) | 具备天然潜质。单一 Leader 维护全序 Replication Log,Follower 严格回放。如果所有读操作强制走 Leader,或采用强同步复制且避免读未提交(Read Uncommitted),即可实现线性一致。 | | **多主复制 (Multi-Leader Replication)** | 否 (No) | 写入可以落到不同 Leader 上,各 Leader 之间短时间内缺乏全局交互,存在写入冲突(Conflict),依靠后续异步解决(Eventual Consistency),无法保证强一致。 | | **无主复制 (Leaderless Replication)** | 极难保证 (学术与工业存在争议) | Dynamo 等系统虽然宣称可配置满足强一致,但存在大量极端边界竞态条件(Race Conditions)。尽管实践中违规概率低,但理论上很难逻辑证明其严格满足。 |

讲者补充探讨了业界实践与理论的矛盾: - **分布式共识(Consensus)与线性一致性**:二者本质等价。若细分,共识算法在语义上等同于在线性一致性存储上实现原子性的 Compare-And-Set(CAS)。 - **DynamoDB 生产暗坑**:Uber 的支付系统曾宣称依赖 Dynamo 的强一致性保证,但讲者透露与同僚(如 Ross)交流时发现,在基于 DynamoDB 处理真实支付业务时,偶尔会出现无法合理解释的诡异丢账/状态异常。无主架构由于竞态条件无穷无尽,修了一个又会浮现另一个,很难给出严格的线性一致性形式化证明。 - **网络延迟代价**:学术界已有论文严谨证明,**保持线性一致性的时间代价与网络延迟(Network Delay)成正比**,这是物理法则带来的硬性开销。 - **纠正对 CAP 定理的误解**:CAP 定理中所谓的“一致性(Consistency)”,其严谨的学术定义就是**线性一致性(Linearizability)**,而非事务中的业务完整性约束。流传甚广的“CAP 三选二”说法在现代分布式系统语境下并不准确,因为网络分区(Partition)是无法避免的客观物理现实,核心抉择其实是在网络分区发生时,系统到底是要选择牺牲线性一致性,还是要牺牲可用性。

[25:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1500s) CAP 定理的真正含义与网络分区的本质

在分布式系统架构中,CAP 定理经常被误解为可以任意三选二。然而网络分区(Partition)并非一个可选项,而是一个必然会发生的故障(Fault)。在运营真实的数据中心时,没有任何系统可以“处死”或假设不存在网络分区;只要时间足够长,正如猴子能在打字机上敲出莎士比亚全集、随机游走终会回到二维平面原点一样,网络分区必然出现。因此,CAP 真正的权衡场景是:**当网络分区不可避免地发生时,系统到底是要选择一致性(Consistency / Linearizability),还是可用性(Availability)?**

如果优先选择可用性,典型代表就是 Dynamo:系统容忍短时间内的不一致,设计首要目标是最大可用(Maximum Availability)。反之,如果系统倒向一致性或线性一致性,就像传统单体关系型数据库配合两阶段提交(2PC),在发生网络分区时直接停止响应,牺牲系统可用性来换取最强的事务一致性保证。

关于网络分区(Network Partition)与节点宕机(Node Crash / Delay)的异同,在共识算法(Consensus Algorithm)和分布式理论视角的本质逻辑如下:

```mermaid flowchart TD accTitle: Network Partition and Delay Equivalence accDescr: 解释延迟、宕机与网络分区在共识算法中的等价性与特例 subgraph S1["等价视角 (Equivalence)"] D["网络高延迟 (Delay)"] -->|"延时1小时/100天"| C["节点宕机 (Crash)"] C -->|"信息不可达"| P["网络分区 (Partition)"] end subgraph S2["脑裂特例 (Split-Brain)"] N["网络对半切分 (50/50 Split)"] N --> L1["Partition A (50% 存活)"] N --> L2["Partition B (50% 存活)"] L1 -.->|"无多数派 (No Quorum)"| L2 end ```

- **延迟与宕机无本质区别**:在计算机领域,如果一个请求延迟达到一个小时甚至一百天,与目标节点彻底宕机在逻辑上毫无区别。大多数共识算法在模型设计上均直接将超时延迟视同宕机。 - **宕机与被隔离(Partitioned)等价**:从系统外部观察者的视角来看,单个或多个节点崩溃,与这些节点因为网络链路中断而与其余网络隔离开来,其黑盒表现完全相同。 - **对称对半切分的特例(脑裂风险)**:存在一种特殊分区,即集群被精准对半切分(各占 50% 权重且节点全部在线,但两半之间彻底断连)。此时任何一边都无法取得严格的多数派(Majority Quorum),可能引发两端并发写入并产生难以解决的数据冲突。 - 只要不同集群或机房之间依然保留着哪怕一条物理连通的链路,在严格定义上就尚未形成完全的网络分区。

---

[30:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1800s) 主从复制架构下的权衡与 SQL vs DynamoDB 的设计初衷

以 MySQL 的 Master-Slave 架构为例,当 Master 宕机时,系统的写可用性立刻归零。此时若要恢复写可用性,就必须执行故障转移(Failover),把某台 Slave 节点晋升(Promote)为新的 Master。但这一晋升过程必然带来一致性损失: - **不进行 Promote**:系统维持强一致性,但写操作不可用(只读可用);等原 Master 节点完全恢复并重新挂载后,主从数据依然保持严格一致。 - **异步复制(Asynchronous Replication)下的 Promote**:旧 Master 与 Slave 之间原本就存在复制延迟差异(Discrepancy)。一旦切主并写入新数据,原本积压未同步的数据就会丢失或被直接丢弃(Data Loss)。 - **同步复制(Synchronous Replication)**:写操作必须等待 Slave 确认,导致单个事务的耗时大幅拉长、延迟(Latency)激增,这在事实上已经牺牲了系统的吞吐与部分可用性指标。

针对关系型 SQL 数据库与 DynamoDB / Cassandra 的设计选型差异,讲者澄清不应笼统地使用模糊的“Consistency”,而要精确到线性一致性(Linearizability):

| 系统类型 | 核心设计诉求 | 机制与权衡 | |:--- |:--- |:--- | | **SQL 关系型数据库** | 偏向**线性一致性** (Linearizability) | 原生针对单对象事务与强一致性设计;通过两阶段锁(2PL)等严格手段保证事务可串行化与线性一致,但未对分区可用性进行极致优化。 | | **DynamoDB / Cassandra** | 偏向**可用性** (Availability / AP) | 从诞生之初就以“服务永不离线”为最高目标;采用宽松法定人数(Sloppy Quorum)、提示移交(Hinted Handoff)等机制,即便牺牲一致性也要保全写可用性。 |

CAP 定理在 2000 年由 Eric Brewer 提出时,恰逢 Napster 等 P2P 去中心化音乐系统萌芽。其历史意义在于打破传统以银行交易系统(Banking Transaction)为基准的强一致性教条,启发数据库设计者不再盲目执着于单点线性一致,而是开拓多维度的架构权衡空间。

---

[35:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=2100s) Kafka 的诞生背景与全序与偏序(Total Order vs Partial Order)

LinkedIn 工程师在开发 Kafka 时的核心观察印证了放宽一致性的必要性:在海量大数据环境下,系统中超过 99% 的日志和数据操作根本不是严格的事务,真正的 Transaction 占比不足 1%。如果为了这 1% 的事务语义去惩罚剩下的 99%,系统吞吐将遭遇严重瓶颈。因此,Kafka 放弃了昂贵的事务保证与即时强一致性,通过将非事务数据先全部打入高吞吐的消息管道中,再推入数据下沉端(Sink)用于离线分析(Offline Analysis)与数据分析计算,开启了以吞吐为第一优先级的流式架构。

在分布式系统因果关系中,操作之间的排列逻辑划分为**全序(Total Order)**与**偏序(Partial Order)**:

```mermaid flowchart LR accTitle: Total Order vs Partial Order accDescr: 对比全序的线性链表结构与偏序的DAG分支结构 subgraph Total["全序 (Total Order)"] direction LR T1["Op 1"] --> T2["Op 2"] --> T3["Op 3"] end subgraph Partial["偏序 (Partial Order - Git/DAG)"] direction TB M1["Commit A"] --> B1["Branch Feature 1"] M1 --> B2["Branch Feature 2"] B1 --> M2["Merge to Master"] B2 --> M2 end ```

- **偏序(Partial Order)**:类似于 Git 分支。多个并发分支(Concurrent Branches)在并行演进时,彼此之间无法也无需排列绝对的先后次序;它们构成的不是链表,而是一个有向无环图(DAG Graph)。只有当这些分支最终合并到 Master 分支时,它们与 Merge 节点之间才建立明确的前后依赖关系。 - **全序(Total Order)**:如同单向链表(Linked List),所有操作都有全局且唯一的前后顺序。线性一致性本质上就是强行在单节点或单状态机视角下对所有跨节点操作拉出一条全序。 - **全序代价高昂**:线性一致性的实现代价直接绑定了网络往返延迟。在数据库的可串行化(Serialization)中,并发事务如果彼此互不冲突,其执行到底是 A 先于 B 还是 B 先于 A 并不重要。从全局来看虽然最终被固化成某种全序落库,但只要满足因果序(Casual Order),系统完全不需要强行去达成昂贵的全序排定。

---

[40:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=2400s) 兰伯特逻辑时钟(Lamport Timestamps)与因果一致性

由于物理时钟在分布式节点之间存在漂移与网络不同步,无法作为严格基准,莱斯利·兰伯特(Leslie Lamport)在早期便提出了**逻辑时钟(Logical Timestamp)**模型,通过因果顺序替代物理时间来进行事件排序。

兰伯特时间戳的构成核心是一个二元组:`[计数器数值, 节点编号]`(例如 Node 2 产生的时间戳)。每个节点内部维持一个自增计数器(Logical Counter):

- **单节点内部序列化**:节点每发生一个本地事件,Counter 单调自增(如 Node 2 本地产生事件序列 $1 \to 2 \to 3 \to 4$),在单节点视角下严格有序。 - **跨节点消息传递与推进**:当客户端携带已知最大时间戳(例如 `Max = 1`)向 Node 2 发送请求时,Node 2 比较本地时间戳(当前为 4)与请求时间戳,取两者中的最大值并加 1,将当前操作标记为 5 并返回,后续新事件再递增为 6。 - **因果一致性保证**:较小的时间戳在因果上被判定为发生在较早阶段。如果两个节点在各自的物理时序内并发执行操作(例如 Node 1 上发生时间戳为 1 的事件,而 Node 2 已经推进到了 2、3、4),在因果顺序中,并发操作之间并无必然依赖,逻辑时钟通过统一的比较规则(时间戳大小优先,时间戳相同时按节点编号破除平局)将它们排成一个满足因果约束的全局序列,既不违反因果逻辑,又规避了昂贵的全局线性一致性开销。

[45:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=2700s) Lamport 时间戳的局限与全序广播的等价性

Lamport 时间戳(Lamport timestamp)的核心设计是在缺乏全局统一真理来源(source of truth)的分布式系统里,通过 `(timestamp, node_id)` 二元组来对事件进行全序比较:优先比较逻辑时间戳,如果时间戳相同,再使用节点编号(Node ID)作为平局决胜条件(tie-breaker)。在发生跨节点操作(cross-node operation)时,接收端会通过同步推进本地逻辑时钟。这样可以确保:如果事件 A 在因果上有向事件 B 传递信息,那么 B 的时间戳一定严格大于 A。它提供了一个明确、无歧义的并发时间戳比较工具(unambiguous concurrent timestamp comparing tool),其本质是保证因果顺序不被破坏(causal order is not violated),提供强有力的因果一致性保证(causal consistency guarantee)。

然而,Lamport 时间戳无法解决所有并发问题。讲者举了一个非常直观的例子:假设两台机器并发申请注册同一个域名(例如注册 `uber.com` 或 `google.com`)。当你收集到两边的 Lamport 时间戳去比较大小时,你已经是在“事后追溯”(after the fact / audit)了。在当下做出决策的那一瞬间,任何一个单机节点都无法知道网络中是否正有其他节点在同一时刻也声称要注册该域名。因此,Lamport 时间戳只能用来做后验审计(audit),而无法在事件发生的当时实时拍板谁先谁后。它无法独立解决并发互斥、全序广播(Total Order Broadcast)、线性一致性(Linearizability)或分布式共识(Consensus)问题。

全序广播在理论上与线性一致性、共识问题是相互等价的(如同 NP 问题的多项式归约等价,虽然理论证明较为繁琐,但核心概念相通)。全序广播必须满足两大核心属性: 1. **可靠交付(Reliable Delivery)**:即 All-or-Nothing,只要广播的消息被交付(deliver)到了某一个正常节点,它就必须最终交付给所有正常节点,绝不允许有消息丢失(no message loss)。 2. **全局全序(Total Order)**:所有节点接收并交付消息的先后顺序必须严格一致(例如节点 1 按照 1、2、3、4 的顺序处理,其他所有节点也必须严格以 1、2、3、4 的顺序处理),否则带有状态的操作(state machine / replication log)就会产生不一致的副作用(side effects)。

全序广播本质上就是单主同步复制(Single-Leader Synchronized Replication)所追求的理想行为:主库与所有从库都持久化并应用了完全一致的事务日志序列后才向客户端返回确认。

---

[50:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=3000s) 两阶段提交(2PC)的机制与“牧师主持婚礼”的比喻

在单机系统中,事务的提交非常纯粹;但在分库分表或分布式系统中,跨分区操作无处不在。最典型的场景就是**全局二级索引(Global Secondary Index, GSI)**:业务数据和它的全局二级索引分片有 90% 以上的概率落在不同的机器分区节点上。当一个事务既修改了基础数据,又需要同步更新跨分区的索引时,系统必须借助原子提交协议(Atomic Commit)来保证二者要么同时成功,要么同时回滚。分布式系统工程师接触工程落地的“第一件大事”,往往就是实现两阶段提交(Two-Phase Commit, 2PC)。

讲者将两阶段提交生动地比喻成一场在教堂举办的**西式结婚仪式**: - **协调者(Coordinator)**:扮演主持婚礼的神父/牧师(或证婚律师)。 - **参与者节点(Database 1 & Database 2)**:分别扮演新郎和新娘。

```mermaid flowchart TD accTitle: Two-Phase Commit Wedding Analogy accDescr: A flowchart illustrating the 2PC protocol comparing the coordinator to a priest and databases to a bride and groom.

subgraph Phase1["第一阶段:准备阶段 (Prepare Phase)"] Coord["协调者 (牧师 / Coordinator)"] DB1["Database 1 (新郎)"] DB2["Database 2 (新娘)"] Coord -->|"1. 写入临时数据并询问: '你愿意娶/嫁吗?'"| DB1 Coord -->|"1. 写入临时数据并询问: '你愿意娶/嫁吗?'"| DB2 DB1 -->|"2. 投出誓言: VOTE COMMIT (Yes) 并持久化"| Coord DB2 -->|"2. 投出誓言: VOTE COMMIT (Yes) 并持久化"| Coord end

subgraph CommitPoint["核心原子提交点 (Atomic Commit Point)"] Log["牧师在结婚证书/小本本上落笔签字<br/>(Coordinator Commit Log 刷盘)"] end

subgraph Phase2["第二阶段:提交阶段 (Commit Phase)"] Coord -->|"3. 判定生效,下发指令"| Log Log -->|"4. 通知确认: 正式成为合法夫妻 (COMMIT)"| DB1 Log -->|"4. 通知确认: 正式成为合法夫妻 (COMMIT)"| DB2 end ```

在第一阶段(准备阶段,Prepare),协调者先把事务数据分别写入 Database 1 和 Database 2(确保数据完全写到位但处于未提交状态),然后牧师走上前询问新郎和新娘:“A,你愿意娶 B 为妻吗?B,你愿意嫁给 A 吗?”在这个阶段,任何一方如果反悔或者由于某种资源不足,都可以直接大喊“No”,那么整场婚礼(整个事务)随即被中止回滚(Abort)。但一旦新郎和新娘郑重回答了“Yes”(即参与者节点回复了 `VOTE COMMIT` 并记录了日志),他们就进入了无法单方面反悔的承诺状态。

---

[55:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=3300s) 不归点(No Turning Point)与协调者单点故障导致的阻塞僵局

当所有参与者都回复“Yes”之后,整场仪式的生杀大权就完全交到了协调者手中。两阶段提交中存在一个至关重要的**原子提交点(Atomic Commit Point)**:牧师正式拿出结婚证书的小本本,在上面落笔签字画押并盖章。在系统底层,这就是**协调者将 Commit 决策写入本地持久化日志(Commit Log to Disk)的物理落盘瞬间**。在这一笔落盘之前,无论参与者怎么表态,整个事务在法律和系统层面上都处于未提交状态;而一旦落盘完成,即使尚未通知到新人,他们在法理上也已经成为合法夫妻,事务已注定生效。

然而,2PC 最臭名昭著的问题在于其应对故障(Failure)时的脆弱性: - **节点早期挂掉**:如果在新娘新郎开口宣誓之前,某一方就突然晕厥逃婚(Node 在 Prepare 之前 Crash),牧师完全可以直接单方面宣布婚礼取消,向所有人发 Abort,逻辑非常干净利落。 - **协调者在关键时刻跑路(Coordinator Failure)**:最致命的场景是,新郎和新娘都已经大声喊出了“我愿意(Yes)”,突然之间牧师被外星人绑架了(Coordinator 宕机失联),或者牧师在落笔前后的瞬间突发意外消失了。此时,新人和任何外界都无从知晓牧师到底有没有在小本本上完成最后那一笔登记。

由于参与者(Node 1 & Node 2)此前已经承诺了“Yes”,出于原子性的保证,它们**绝对不能自行擅自 Abort**——因为牧师可能在消失前的最后一微秒已经完成刷盘认定了提交;但它们也**无法自行决定 Commit**。两个数据库节点只能被迫在原地无限期死等(Stuck / Block),直到失联的协调者重新上线。更严重的是,为了防止发生写冲突,该事务所触碰修改的所有数据行(Row Locks)都会被全部牢牢锁死,任何后续并发的写事务都会被彻底阻塞(Block)。

---

[01:00:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=3600s) 2PC 的性能代价与共识算法的四大核心属性

协调者的单点脆弱性和阻塞机制直接导致了两阶段提交极其糟糕的性能表现: - **吞吐量出现数量级的断崖式暴跌**:现代单机数据库每秒能够轻松处理数万到数十万($10^4 \sim 10^5$ 级别)个事务;但一旦引入跨节点的两阶段提交,由于多轮网络往返开销以及长期的跨节点锁持有,吞吐量往往会直接跌落到每秒 1000 次甚至仅 100 次事务,性能开销暴跌一到两个数量级。 - **运维需要人工介入**:一旦协调者服务器遭遇不可恢复的硬件损坏(“律师彻底跑路再也回不来了”),机器协议本身是无法自愈破局的,必须依赖系统管理员手动介入去检查各参与者日志、强行决定到底是 Commit 还是 Rollback,以解除数据库挂起的锁。这也是业界在构建高并发系统时极力避免无脑采用 2PC 的根本原因。

为了在无须中心化单点协调者的前提下达成容错一致,计算机科学家引入了**共识算法(Consensus Algorithm)**。一个合格的共识算法必须严格满足以下四个核心属性:

| 核心属性 | 英文定义 | 核心含义与机制说明 | |:--- |:--- |:--- | | **一致同意** | **Uniform Agreement** | 任何两个节点决定的值必须相同。系统绝不允许出现节点 A 认定结果为 X(例如觉得中国发达、TikTok 好玩),而节点 B 认定结果为 Y(觉得美国发达、Facebook 好玩)的分歧分裂。 | | **完整性 / 单次决定** | **Integrity** | 每个节点对于一个共识实例最多只能做出一次决定(Decide at most once),做出决定后不可出尔反尔(例如决定去吃麦当劳后,不能在同一实例中又反悔说改成去吃肯德基)。 | | **有效性** | **Validity** | 最终被决定出来的任何值,必须是由某个参与节点所提议出来的(Proposed value),绝不能凭空捏造。如果缺乏该属性,共识协议就会变得极其平庸(Trivial)——所有节点只需要无脑硬编码统一返回 `0` 即可轻松满足前两条,但这样的结果毫无实际业务价值。 | | **终止性 / 活性** | **Termination** | 只要系统中有未崩溃的节点(Non-faulty nodes),系统最终就必定能做出一个决议。该属性保证了算法的活性(Liveness),防止系统陷入无休止的死锁或阻塞状态。 |

对照这四大属性可以发现: - 如果抛开 **Termination(终止性)** 不谈,前面讲的**两阶段提交协议**以及**单主复制(Single-Leader Replication)**都是能够满足共识的前三个要求的。因为在正常情况下,由 Master 统一指定一个合法提议值,推送到从库,节点间值一致且不反悔。 - 但**单主复制无法保证 Termination**:一旦主库(Master)挂掉且从库无法自发达成一致重新选举时,整个系统就无法继续做出决议并继续向前推进。真正的分布式共识协议要求在部分节点宕机的前提下,剩余的存活多数派从节点仍能自动推进决议。

讲者最后提到,学术界与工业界现有的主流成熟共识算法脉络相对清晰,其中最著名、最经典的基石是 Leslie Lamport 提出的 **Paxos** 算法,后续工业界也涌现出了像 **Raft** 这样更易理解与工程实践的共识算法实现。

[01:05:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=3900s) 从 Paxos 到 Raft:为什么分布式共识需要更容易理解的算法

Paxos 算法在分布式领域虽然经典,但其理解与工程实现极其复杂。Leslie Lamport 在提出 Paxos 后,为了让同行和工程师真正搞懂,后续写了多篇简化版的论文进行解释(例如经典的《Paxos Made Simple》),但其繁杂的边界特例(corner cases)依然令人头疼。正因如此,斯坦福大学的教授与学者在 2013 至 2014 年间提出了 Raft 算法,并获得了 2014 年 USENIX ATC 的最佳论文奖(Best Paper)。在分布式系统领域,三四年的新技术一般属于尖端前沿(cutting-edge),五六年的系统或算法才会逐渐成为工业界主流,若时间更短则仍停留在纯学术研究阶段。Raft 的核心目标非常直接:在安全性与一致性保证上与 Paxos 等价,但大幅简化角色定义与状态变迁(明确拆分为 Leader、Follower 与 Candidate),彻底降低理解与工程落地的门槛。

通过浏览器中运行的可视化动画可以直观地观察 Raft 的选举机制。每个节点内部都维护一个倒计时定时器(election timeout)。在工业界系统中,超时时间各有取舍:像 HBase 这类系统通常设计为数秒(如 7 到 9 秒的较长超时),而很多对延迟敏感的分布式数据库则将超时设在几百毫秒(例如 300 至 500 毫秒),极端激进的设计甚至只有 100 到 300 毫秒。在任期(Term)概念中,Leader 会在当前 Term 内周期性地向所有 Follower 发送心跳(Heartbeat)进行续期(refresh)。如果 Leader 宕机或网络中断导致 Follower 在 timeout 时间内未收到心跳,该 Follower 便会自增 Term、将自身角色切换为 Candidate,并发起新一轮选举。

- **核心角色划分**:Leader(负责处理请求并发送心跳)、Follower(被动接收日志与心跳)、Candidate(超时后发起拉票选举)。 - **任期演进示例**:在动画模拟中,15 秒后由于节点超时,Leader 从节点 S2 转移到了 S5,Term 从最初的 1 或 2 跃升为 4;当随后的节点检测到心跳丢失超时后,会再次将 Term 推高至 5 并自荐为候选人,向集群广播拉票。

```mermaid flowchart TD accTitle: Raft Node State Transitions accDescr: State machine transitions between Follower, Candidate, and Leader in Raft consensus algorithm.

subgraph RaftStates["Raft 节点状态机"] F["Follower<br/>跟随者"] C["Candidate<br/>候选人"] L["Leader<br/>领导者"] end

F -- "Election Timeout<br/>未收到心跳" --> C C -- "收到多数票<br/>Quorum Votes" --> L C -- "发现更高 Term<br/>或合法 Leader" --> F L -- "发现更高 Term<br/>心跳失败/降级" --> F C -- "选举平票/超时<br/>Split Vote" --> C ```

---

[01:08:30](https://www.youtube.com/watch?v=gaogvQVJVxw&t=4110s) Raft 的核心机制:Term、Timeout 与 Heartbeat 的权衡

心跳频率(Heartbeat Frequency)与选举超时(Election Timeout)之间的参数配比,直接决定了共识系统的稳定性和故障恢复速度。根据 Raft 论文的建议,心跳发送间隔应当比超时时间小一个数量级(即相差约 10 倍)。例如,若选举超时时间设定为 10 秒,心跳频率最高应设为 1 秒;若超时时间为 500 毫秒,心跳发送间隔则应压缩至 50 毫秒甚至更低。这种比例配置是为了防止网络出现微小抖动时,心跳无法及时送达而引发误判。

系统设计中存在着无法避免的权衡: 1. **心跳过于频繁(间隔极短)**:系统对瞬时网络延迟极为敏感,网络抖动容易被误判为节点死机,从而频繁引发不必要的再选举(spurious elections); 2. **心跳过于稀疏(间隔较长)**:系统故障恢复反应迟钝。若 Term 设置为 10 秒且心跳 1 秒才发一次,当 Follower 刚好在心跳刚过的那一瞬间死机,整个系统在长达一秒的时间内都无法感知该节点的脱机状态。

- **参数经验法则**:$\text{Heartbeat Interval} \ll \text{Election Timeout}$(通常小一个数量级)。 - **心跳网络代价**:在数据中心环境中,网络带宽与延迟是最宝贵、最容易成为瓶颈的资源,过于频繁的小包通信会直接消耗宝贵的网络链路能力。

---

[01:11:45](https://www.youtube.com/watch?v=gaogvQVJVxw&t=4305s) 共识算法的实际用途与理论边界(FLP 不可能性定理)

为什么分布式系统必须依赖共识?在单主复制(Single-Leader Replication)架构中,系统决不能把 Leader 写死在配置中;一旦当前 Leader 宕机,必须由 Follower 自动顶上。在没有绝对权威中心、网络通信充满不确定性的环境中,让所有节点自发决定出谁是新的合法 Leader,本质上就是依靠共识算法。如果没有共识,节点 A 认为结果是 2,节点 B 认为结果是 3,系统便彻底丧失了单一事实来源(Single Source of Truth)。除选主外,共识机制还广泛应用于动态成员管理(Membership Management,如平滑增删节点 S6 替换 S4 时保证 Quorum 判定合法)、协调服务(Coordination Service,如 ZooKeeper 与 etcd)、工作分配(Partition Leader 选举,防止脑裂导致数据损坏)以及服务发现。

然而,分布式共识在理论上存在一道坚固的边界——**FLP 不可能性定理**(由 Fischer, Lynch, Paterson 于 1985 年提出)。该定理证明:在异步网络模型(Asynchronous Network,即网络延迟无上限/无界)且哪怕只允许一个节点可能发生崩溃崩溃故障(Crash Failure)的前提下,没有任何确定性共识算法能够保证必定收敛达成一致。在实际运行中,如果网络发生严重分区或特定链路断开,Raft 可能会出现两个候选节点反复相互抢占选票的活锁状态(类似 split-vote 引起的 consensus storm),导致长时间无法选出 Leader。所幸工程实践中通过引入随机化选举超时(Randomized Election Timeout)等机制,使得算法在绝大多数实际场景下能够极快收敛。

- **共识的核心应用**: - **成员关系变更**:节点动态上下线、集群伸缩过程中的仲裁安全性。 - **协调服务实现**:ZooKeeper 实现了类 Paxos 协议(ZAB),而 etcd 则直接基于 Raft 打造。 - **防止状态分裂**:对多分区(Partition)归属做出一致认定,杜绝双写数据污染。 - **开源生态演进**:Kafka 在 2018 年前后推进了基于 Raft 的自研共识机制(KRaft),逐步将历史包袱 ZooKeeper 剔除替换;社区中如 Python 等各类语言也都相继产出了 Raft 的独立实现。

---

[01:17:15](https://www.youtube.com/watch?v=gaogvQVJVxw&t=4635s) 答疑一:Gossip 协议与共识算法的本质区别

有听众提问 Cassandra 使用的 Gossip 协议是否也属于共识算法,以及它是否通过机器间的交互来探查节点宕机。对此,两者的设计目标和运行原理截然不同:**Gossip 并不属于共识算法**。共识算法的核心目标是在每一个明确的时间点上,集群内对“谁是 Leader”或“某个决议的值是什么”必须达成一致且无歧义的裁决;而 Gossip 本质上是一种用于数据广播与扩散的最终一致性通信模式(Broadcasting Pattern)。

在数据中心内部,网络是最昂贵、最容易遭遇瓶颈的资源,优先级与成本远高于廉价的 CPU 和内存。如果一个节点拥有最新数据后直接对所有节点发起全量单点广播(Broadcast),其出站链路(Output Link)带宽将瞬间被打爆成为系统瓶颈。Gossip 巧妙地解决了这个问题:节点 S5 将数据传给 S4,随后由 S4 和 S5 在下一周期分别传给 S2、S3,将巨大的网络广播压力随时间推移分散到集群的所有节点上,最终达成状态同步。

| 比较维度 | 分布式共识协议(如 Raft、Paxos) | 流行病协议(Gossip Protocol) | |:--- |:--- |:--- | | **核心目标** | 强一致性、确定性裁决(如选主、状态机日志) | 数据异步广播与扩散、最终一致性 | | **时间敏感度** | 毫秒级检测(心跳通常在 20ms~50ms,超时数百毫秒) | 秒级周期性交换(允许节点状态滞后数秒) | | **网络行为** | 高频固定点对点通信,要求 Quorum 立即确认 | 随机周期性扇出通信,降低单节点网络负载 | | **典型系统** | etcd, ZooKeeper, Raft 集群 | Apache Cassandra, Consul (Serf 成员层) |

关于成员检测(Membership),共识系统里的心跳检测是参与投票与维持 Leader 权威的前提,必须极其高频;而 Gossip 在 Cassandra 中主要为了探测节点是否在线及传输集群元数据,容忍节点短暂失去响应(两三秒内无响应并不立即导致全局系统瘫痪),两者所承载的业务职责大相径庭。

---

[01:24:45](https://www.youtube.com/watch?v=gaogvQVJVxw&t=5085s) 答疑二:两阶段提交(2PC)中的 Participant Failure 恢复机制

针对两阶段提交(Two-Phase Commit, 2PC)中参与者(Participant)在不同阶段发生故障的应对策略,讲者通过生动的“教堂婚礼”比喻进行了深入剖析:

```mermaid flowchart TD accTitle: Two-Phase Commit Participant Failure Handling accDescr: Workflow showing coordinator and participant recovery paths during participant failure in 2PC.

subgraph Phase1["阶段一:Prepare 阶段"] P1["协调者发送 Prepare 请求<br/>询问参与者是否准备就绪"] P1_Fail["参与者挂掉 / 超时未响应"] P1_Abort["协调者判定全局 Abort<br/>回滚本地及各参与者事务"] P1 --> P1_Fail --> P1_Abort end

subgraph Phase2["阶段二:Commit 阶段"] P2["所有参与者均回复 Yes<br/>协调者日志写入 Commit 决议"] P2_Fail["某参与者在回复 Yes 后死机<br/>未收到 Commit 命令"] P2_Retry["协调者必须持续重试 Ping<br/>直到参与者恢复并确认"] P2_Pull["参与者重启后主动拉取<br/>查询协调者 Transaction Log"] P2 --> P2_Fail P2_Fail --> P2_Retry P2_Fail --> P2_Pull end ```

1. **准备阶段(Prepare Phase)故障**:在参与者准备写入数据阶段,如果参与者挂掉导致协调者(Coordinator)迟迟收不到答复,处理方式非常直脆清晰——直接将事务判定为中止(Abort)。这就像牧师询问新娘“你愿意嫁给新郎吗?”,新娘如果毫无反应或直接晕倒,婚礼直接宣布告吹。 2. **提交阶段(Commit Phase)故障**:若新娘说出了“Yes”但该应答未被牧师收到,牧师由于超时可能会直接记录 Abort。参与者苏醒后需要主动查询协调者的事务日志(Coordinator Log)来确认事务最终状态。 3. **最棘手的故障挂起**:若协调者已经收集齐了所有参与者的“Yes”,并在本地 WAL 日志中永久写入了“Commit”决议,此时某个参与者突然死机脱机。根据 2PC 协议规范,协调者决不能放弃,必须在后台不断轮询重试(Ping)该节点直到其复活,确保其完成提交;同时,死机恢复后的参与者也会主动向协调者拉取决策(Pull),确认自己先前投票的事务究竟是 Commit 还是 Abort。

---

[01:27:30](https://www.youtube.com/watch?v=gaogvQVJVxw&t=5250s) 答疑三:线性一致性(Linearizability)的观察与验证

听众提出了关于线性一致性(Linearizability)与时效性保证(Recency Guarantee)的辨析:是否必须要求一旦有请求读到了最新写入的值,后续所有请求就必须绝对读到最新值?在第一个读到最新值的请求之前,是否允许其他请求读到旧值?

讲者指出,该提问描述的现象完全符合线性一致性。线性一致性本质上是从**外部可观察性(Observability)**的角度建立的因果与全局时钟映射: - 在没有全局绝对时钟(Oracle)直视系统内部真实物理写入点时,外部观察者只能依据客户端发起的请求区间(从发起调用到收到响应的物理时间段)来进行判定。 - 只要能在逻辑上为所有操作找到一个符合“读写在调用和返回之间某一个虚拟瞬间原子生效”的全局线性全序(Linear Order),且该全序不违背真实物理时间的因果先后关系,系统就是满足线性一致性的。 - 只有当外部观察者捕获到了明确的违例反例——例如客户端 A 的读取操作已经完全结束并拿到了最新值 4,随后客户端 B 发起的一个全新读取操作却返回了旧值(如读取到了 2),才会彻底“戳破”线性一致性的成立假象。如果客户端 B 的读取区间与客户端 A 存在哪怕一点点时间重叠,系统依然能够将两者的执行次序解释为合法串行,从而继续满足线性一致性。

---

[01:30:15](https://www.youtube.com/watch?v=gaogvQVJVxw&t=5415s) 总结与读书会形式探讨

讲者感叹,本书第 11 章(Consistency and Consensus)是整本书中最为复杂烧脑的篇章之一。深入推导各种网络分区、时钟偏差与异常 Counter Cases 的边界情况,极易让人思维陷入死胡同。今天作为理论部分的最后一讲告一段落。

在分享形式上,讲者提到为了准备这次 slides 花费了极其繁重的时间精力,必须先重读一遍章节、将过于深奥的内容抽丝剥茧并整理通俗讲法,有时备课过程本身就把自己也绕晕了。讲者提议后续如果继续推进,可以转变为更为轻松可持续(sustainable)的“读书讨论会”模式——大家每周自主研读一章,会上直接交流心得体会与答疑解惑,不再由单人承载制作精细 slides 的重负,这样能够让分享活动更加长久地维持下去。最后,讲者向所有与会者表达感谢并结束了本次录制。

## Notable quotes > [00:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=0s) 把复杂的分布式多节点系统抽象得像一台单机数据库一样简单 — Scott Shi

> [05:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=300s) 你真的不知道怎么解释的时候,需要你比较有想象力 — Scott Shi

> [20:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1200s) 保持线性一致性的时间代价与网络延迟(Network Delay)成正比 — Scott Shi

> [25:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1500s) 当网络分区不可避免地发生时,系统到底是要选择一致性(Consistency / Linearizability),还是可用性(Availability)? — Scott Shi

> [25:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=1500s) 如果一个请求延迟达到一个小时甚至一百天,与目标节点彻底宕机在逻辑上毫无区别 — Scott Shi

> [35:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=2100s) 在海量大数据环境下,系统中超过 99% 的日志和数据操作根本不是严格的事务,真正的 Transaction 占比不足 1% — Scott Shi

> [45:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=2700s) 当你收集到两边的 Lamport 时间戳去比较大小时,你已经是在“事后追溯”(after the fact / audit)了 — Scott Shi

> [55:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=3300s) 协调者将 Commit 决策写入本地持久化日志(Commit Log to Disk)的物理落盘瞬间 — Scott Shi

> [01:05:00](https://www.youtube.com/watch?v=gaogvQVJVxw&t=3900s) 在安全性与一致性保证上与 Paxos 等价,但大幅简化角色定义与状态变迁 — Scott Shi

> [01:17:15](https://www.youtube.com/watch?v=gaogvQVJVxw&t=4635s) Gossip 并不属于共识算法 — Scott Shi

## Mentioned Scott Shi, Redshift, Scala, Twitter, LA Lakers, Dynamo, DynamoDB, Uber, Ross, MySQL, Cassandra, Eric Brewer, Napster, LinkedIn, Kafka, Git, Leslie Lamport, Paxos, Raft, Stanford University, USENIX ATC, HBase, ZooKeeper, etcd, Fischer, Lynch, Paterson (FLP), Consul, Serf, TikTok, Facebook, McDonald's, KFC

## Video description Recorded Date: Aug 27, 2020 Doc for this video: https://docs.google.com/presentation/d/1tNNd5njQ5EK3eCnzzwhKXPKEiVbkvJQJDRnhKNmh7yU/edit?usp=sharing

[Source](https://www.youtube.com/watch?v=gaogvQVJVxw)

中文简报

Raft以多数派机制化解2PC阻塞 确立分布式共识标准 保持线性一致性的代价直接受制于网络延迟,传统两阶段提交因协调者单点故障易致系统死锁,工程落地须依托Raft等共识算法由存活多数派自动推进决议。 本次分享全面剖析了分布式系统领域最核心也最复杂的一致性与共识机制。讲者深入辨析了线性一致性与可串行化的边界,剖析了 CAP 定理下网络分区的必然性,并梳理了全序、偏序以及兰伯特逻辑时钟的适用场景与局限。随后,内容以生动的“教堂婚礼”比喻剖析了两阶段提交(2PC)的阻塞瓶颈,系统阐释了共识算法的四大核心属性,并对比了 Paxos 与 Raft 的设计演进及 FLP 不可能性定理。最后,讲座就 Gossip 协议与共识的区别、2PC 故障恢复路径以及线性一致性的外部观察等实际疑问进行了深入解答。 线性一致性(Linearizability)本质上是针对外部观察者的最新性保证(Recency guarantee),在数学等价上与全序广播及分布式共识互为充要映射,且其时间开销与网络延迟严格成正比。 (20:00) CAP 定理常被误解为三选二,但在真实的分布式环境中网络分区是无法消除的物理现实,实际权衡核心在于网络分区发生时选择牺牲线性一致性还是可用性。 (25:00) 两阶段提交(2PC)因协调者单点故障与阻塞机制会导致系统吞吐出现数量级暴跌(如从单机十万级跌至百级),且单主复制与 2PC 均无法保证共识所需的终止性(Termination)。 (60:00) Raft 算法通过拆分角色与任期机制降低了 Paxos 的工程实现复杂度,但受限于 FLP 不可能性定理,异步网络中不存在绝对能收敛的确定性共识算法,工程上依赖随机化超时破局。 (71:45)

Reading summary

讲者 Scott Shi 阐明了分布式系统中的核心权衡:在物理延迟与网络分区必然发生的现实下,系统无法兼得全序的线性一致性与极致的可用性;而分布式共识算法通过规范状态机演进与多数派表决,解决了单点协调阻塞难题,成为分布式容错系统的基石。 线性一致性的本质与时序判定 (0:00) 线性一致性(Linearizability)旨在将复杂的分布式系统抽象为单机数据库实例,保证最新写入即时可见。讲者辨析指出,线性一致性与事务隔离级别中的可串行化互不包含:例如可串行化快照隔离(SSI)虽保证事务串行等价,但事务可能读取旧快照,违反线性一致性;而针对单对象的线性写入则缺乏跨对象事务的原子性。判定系统是否满足线性一致性,关键在于能否在各客户端读写调用的耗时区间(发起至响应)内找到合理的原子生效点,并投影到单一虚拟时间轴上。若某个读操作的发起时间严格晚于另一个读到最新值(如 4)的操作完成时间,却读回了旧值(如 2),系统便构成了时序倒退违规;但若两者物理窗口存在重叠,则仍可通过合法串行化解释挽救其一致性。 网络分区的物理现实与 CAP 权衡 (25:00) 讲者指出流传甚广的 CAP“三选二”并不准确,因为在真实数据中心运营中,网络分区是必然发生的故障而非架构选项,长时间的高延迟在共识模型中亦等价于宕机。系统的核心抉择在于当分区不可避免地出现时,究竟是倒向可用性(如 DynamoDB 采用宽松法定人数与提示移交,容忍短时不一致),还是倒向强一致性(如传统 SQL 数据库配合严格锁机制,在分区时停止服务)。此外,根据 LinkedIn 在 Kafka 开发中的洞察,大数据环境下超过 99% 的操作并不需要强事务语义;强行拉出全局全序的开销受制于网络往返延迟,现代流式与分布式架构通常仅维持 Git 式的分支偏序与因果一致性,以此换取高吞吐。 两阶段提交机制与单点阻塞脆弱性 (50:00) 跨节点分片操作与全局二级索引(GSI)更新常依赖两阶段提交(2PC)。讲者将 2PC 比作教堂婚礼:协调者扮演牧师,参与者节点扮演新人。第一阶段协调者发起准备询问,各参与者执行预写并持久化投出 Commit 选票;第二阶段当且仅当协调者将最终决议刷入本地 Commit Log 时,系统达到原子提交点并下发确认。然而 2PC 存在致命的单点阻塞脆弱性:一旦参与者均已回复 Yes 且锁定数据行后协调者意外失联,参与者无法获知最终决议,既不敢自行提交也不敢擅自回滚,导致事务无限期挂起并死锁并发写入。该协议的多轮网络往返与锁竞争往往使系统吞吐量由单机的数万次断崖式跌落至数百次,严重硬件故障时还必须依赖人工排障干预。 分布式共识属性、Raft 与理论边界 (65:00) 为了在无单点协调者的前提下推进系统,分布式共识算法必须满足一致同意、完整性、有效性与终止性(Termination)四大属性;单主复制和 2PC 正是因为主节点宕机后无法保证终止性而不能算作完备共识。针对 Paxos 实现过于复杂的痛点,斯坦福学者提出的 Raft 算法通过明确拆分 Leader、Follower 与 Candidate 角色,基于任期(Term)与超时心跳实现状态流转,工程上通常要求心跳发送间隔比选举超时小一个数量级以避免误判与抖动。讲者同时澄清,Cassandra 等系统使用的 Gossip 协议属于低网络开销的数据异步广播模式,并非用于确定性裁决的共识算法;而在理论层面,根据 FLP 不可能性定理,在网络延迟无界的异步模型下哪怕仅单节点故障,也不存在必定能收敛的确定性共识算法,工业界主要依赖随机化选举超时在绝大多数场景下达成快速收敛。 讲者总结指出,一致性与共识是分布式系统中最复杂的理论基石。受物理网络延迟与 FLP 不可能性定理的硬性约束,工程实践的核心不是盲目追求单点线性一致性,而是看清全序与偏序、延迟与吞吐之间的客观取舍,按业务容忍度设计架构。

Source quotes

[0:00] Scott Shi: 把复杂的分布式多节点系统抽象得像一台单机数据库一样简单 [5:00] Scott Shi: 你真的不知道怎么解释的时候,需要你比较有想象力 [20:00] Scott Shi: 保持线性一致性的时间代价与网络延迟(Network Delay)成正比 [25:00] Scott Shi: 当网络分区不可避免地发生时,系统到底是要选择一致性(Consistency / Linearizability),还是可用性(Availability)? [25:00] Scott Shi: 如果一个请求延迟达到一个小时甚至一百天,与目标节点彻底宕机在逻辑上毫无区别 [35:00] Scott Shi: 在海量大数据环境下,系统中超过 99% 的日志和数据操作根本不是严格的事务,真正的 Transaction 占比不足 1% [45:00] Scott Shi: 当你收集到两边的 Lamport 时间戳去比较大小时,你已经是在“事后追溯”(after the fact / audit)了 [55:00] Scott Shi: 协调者将 Commit 决策写入本地持久化日志(Commit Log to Disk)的物理落盘瞬间 [65:00] Scott Shi: 在安全性与一致性保证上与 Paxos 等价,但大幅简化角色定义与状态变迁 [77:15] Scott Shi: Gossip 并不属于共识算法

Original transcript

[0:00] Thank you. Thank you. I talked about it, but did you hear me? Thank you for listening to me. Thank you. Thank you. Oh So I just talked a few days ago, no one could hear me saying anything. I just said, I'll just say this. I'm sorry, I thought you could hear me. I'm not sure if I can hear you. I'm not sure if I'm talking about this mic. I can see it very fancy, but it's pretty bad. Okay, I can see it very fancy. I'll just say this. I'll just say this. I'll just say this. We talked about consistency and consensus. And then And this consistency is there two consistency? One is a database consistency, and one is a consensus consistency. And the database consistency, for example, in a period of time, there are two people on call. And this consistency is a client logic. The database doesn't care. That's false. That's a client logic of consistency. But we're talking about consensus consistency. It's a different replica of data and replica of different replicas. And this is because we are doing this replicate data. Data is actually to ensure at least one of the pieces. And the reason is that if you have one, you can use the server data, right? It can guarantee durability. So when one data center is broken, you can still read the data center. So consistency is very different. So we need to make sure that consistency is data based consistency or distributed system consistency. And this part, the main thing is distributed system consistency. And distributed system consistency is definitely going to exist. Because we have data replica, it will definitely exist. the replica, synchronized replication, so you can do committed data is not Inconsistent, but you actually have to do it in consistent. The on-committed data is still inconsistent. So consistency, because it's replication of the value, it's definitely存在. So we're talking about consistency. So we discussed the first distribution system of the concept. The first distribution system is to do the first distribution system. That's the distribution system. It's to simple simple. Simple is what? It's a lot of systems, but you want it to be a database. So it's called Lineability. So, if you have the storage behind the back, whether it's primary or secondary, or master/slave, or master/master, or whatever the database is replicated, From my client's perspective, you feel like in the same database. I feel like in the same way, I just have a database interaction. So this is Linearability's definition. [5:00] 然后这个Linear Benetting和Serialization是不一样的因为这两个是不一样的,最常见的不一样就是,比如说这个snapshot, Serialized Snapshot Isolation它是满足Serialization,但是不满足Linearability的,因为它不满足Linearability的原因是你这个Linearability应该是读的是,就是你读的是最新写的Data,但是你这个,你这个就是Snapshot Isolation,如果你有一个Transaction长的话,你读的是Still Data,是吧?所以它是不满足Linearability的但是另一方面如果你满足Linearability你不一定满足Serialization一个简单例子比如说你有多个Object去写的时候多个Object去写的时候你对于每个Object来说都可能都满足Linearability然后但是对于总体来说你可能不满足Serialization 是吧你对于整个多个Object的写你可能不是同时写入或者是Oh, Nothing, Serialization可能是不guaranteed的总体来说这个是其实非常复杂的一部分,大部分面试也不会考虑,但是对于你的理解来说,特别你要设计一些跟Teta Base相关的,不是这种casual的,不是这种你允许data loss啊,或者是这种的话,你可能都会有就是,可能会有所帮助。其次的话,你也可以就是帮你argue一些非常奇怪的case,是吧?然后我最近遇见了一个特别有趣的Case就是我们deploy一个coder嗯我老婆deploy code,然后她那个file descriptor直接往上找然后它有一个file descriptor leak,然后我们仔细看一下那个configuration好像没有 leak,然后它那个call还是一个redshift的call,所以它call非常infrequent然后它那个file descriptor是每半小时早大概好几千,大概早应两千,就是你file descriptor每半小时leg大概两三千所以就很奇怪,非常 weird scenario 是吧,然后我们就,现在没有讲解为什么,但是你就知道这个computer system里面,所有的 weird scenario 都可能haven它是用 Scala 写的,所以这个有可能是 lazy class load 的,因为 Scala 会 compile 从 java 执行所以有可能是这种lazy的class load,然后open了什么,但是我们现在的话还没有调查出来然后你看其他的那个就是包括其他的Engineering做Blog的时候,你也看到很多奇怪的东西啊比如说我记得我记得有个这个Twitter给了一个talk是叫Skill的TTL然后它造成的原因就是就是Twitter它做了很多cash比如说它对这个胡人队的这个胡人球队Los Lakers profile就是主页Company Profile和Brand Profile做了一个你搞Cache,然后你读这个Cache的时候,你就会看到这个忽人队主页,然后你不需要去读Database。然后这是一个真实的incidence,大概在2013年还是2014年的时候,你实际上访问不了胡门栋组业了,就是你去胡人队的组业,它会显示的是,没有组业就是NOT,就是Page Not Found, 404,然后他定了当时给的TekTok的原因是,他们不知道为什么他只知道的是他们当时开始 expired 然后去 database 读但是 somehow 读到了一个一个now value,然后这个now value被cash了12个小时就是说你现在你database这个cache value expire了,然后去database里面读一个字,这个是有一个talk,也有一个tagtalk的,你可以搜一下叫skill的ttl,然后然后去读database的值,然后读了一个NOT,然后这个NOT是被固定的开始12个小时,所以这个胡人队组业在12个小时内就是NOT FOUND然后这个12个小时的Cash Value expired 了以后呢,然后它还显示出那个互人队组业了。对于这个公司来说就是一个 big outage,他们花了很多地方时间去做这个 post analysis,分析不出原因来。所以这个talk 也很有趣,就是它当然设计了一些比较简单的方式来解决它,但是到底是什么原因?其实不知道的。你有一些很奇怪的东西你是很难看出来的原因并且这种东西的话即bug式即接耗时你很难解释的原因所以有时候说我们学的很深入,就是说学那么多transaction东西和linearability东西有什么作用?我觉得很大一个作用就是你真的不知道怎么解释的时候,就说potentially什么事情可能happen,这时候就需要你比较有想象力了需要比较有想象力,写程序的时候有想象力还是挺重要的好,这边的话就是说,Linear Billionty,其实是我觉得在工作中还是挺常见用的一个东西,因为这个就是经常会经常会经常 [10:00] 造成一个inconsistent的东西或者造成一个outage或者造成一个一个wrong answer然后这时候你就可能思考一下这个系统里面哪块没有满足linearability的问题然后我们看一下解释linearability的这个图我们看到这里的话,它其实是有多个Client在进行操作的。这个CAS是ComparedSet,就是先对比。比如说CASX24,就是先对比X值是不等于2。如果X等于2的话,把它set成4,就是ComparedSet。所以这个就是CAS所以我们看这块的话,它其实是有多个Client进行操作的首先是有一个,就是这个Client D在Write的这个,把X的设置成0,然后返回了OK然后它真正那个Automic Operation,就是说我们一直在强调一个Transaction和Lineability,一直在强调一个Automic Operation,就是在那个时间点之前你这个操作是没有 committed的,在那个时间点之后的操作是 committed的。它这个 atomic operation 是画成这个灰色的线,然后对应到这个时间轴上。所以呢,我们可以看到从这个Client的这个D的角度来讲,它是先把X写成0然后呢对比x是不是等于0,如果x等于0的话,把x4乘3,然后它fill掉了,因为这时候x不等于0了然后从climb c的角度来讲呢它是首先读了一下x的值然后读出x等于1然后又读了一下x的值读出x等于2然后在x等于2的情况下做了一个compared set然后把x设置从4然后最后返回是OK了如果从ClientB的角度来讲的话它首先是读X的值然后读Z是1然后做了一个Comparside,然后把这个X的值变成了2,然后这个Comparside是成功了,然后再读X的值,然后它这个X的值读出来2,然后这个值呢其实是有问题的,我们一会稍后看为什么这个值是violateLineability的然后这上面这个讲的就是什么呢?就是,上面ClientA呢是先把X的值写成了1,然后再读X的值,然后读出了4,好,这是所有的Client,就是我们每一个Client进程单独思考了一下。如果我们把它整合的话,你会发现这个时间轴是这样子的。首先这个Client D 呢,首先把X写成0。我们注意到,Client D 在把X写成0的时候,它其实返回给这个Client OK,其实是持于Client A 的。所以Client A在ClientD还没有写入X等于0的时候已经知道X就是已经把x等于1覆盖过去了如果它这块进行读的话比如说这个clientB来说clientB进行读的时候他读的时候这个值,他其实在这个读呢,是在这个地的写之前的,所以他这个开始时间是在大家写之前的。但是他这个读的时间其实在X写0和X写1之后的所以这个就是说,虽然它结束的时候,我们看这块这个例子其实相对来说比较比较有趣的,就是说在Client B读到X=1的时候最早的鞋还没有返回最早的写是这个x等于0的写还没有返回给clientD,然后clientB就读出来x等于1了这个是OK的,因为我们说在这个distribute system里面,你这个message是可以delay很久的。所以你这个写的时间,就是你最后拿到answer的时间,不一定是在database先后顺序发生的时间。就是在 database 先后的讯息发生时间不一定是拿到 answer 的时间所以这种情况下的话,这个操作是不违反 Linearability 的因为它就是存在一种time window它存在一种time window是什么呢?就是Client D 还没有写入的时候或者clientD写入了以后然后clientB进行读的操作然后读到这个值虽然clientB在这个操作之前是吧然后clientB还有一种可能结果是什么呢就是它的读的操作在这儿的就是在这个clientD写入之前那这样的话它会返回的一个结果是没有读到任何纸他没有读到任何值是吧所以这种情况下的话也是一个 valid answer 也是没有违反 linear ability 的我们就说比如说就只有两个 operationD进行写的操作然后在这块返回OK了然后B进行读的操作然后B读的操作是在他写之前的然后他返回是在很久之后的假设只有两个那这个也是满足 Linearability 的因为你不知道它整个这个transaction里面具体的读和写记在什么时候它存在一种possibility存在一种 possibility 它的读是在它写发生之前的那么如果它存在这种 possibility 的话它是不违反这个 linear ability 的也就是说你只要存在一种possibility,来把所有的这个database写和读,然后投影到像这种情况下,把所有database写和读,同意到同一个时间走上同意到一个Single Deja Base 上 [15:00] 能解释它,然后它没有 violation那他就不违反这个linearity所以我们看这种情况下,这个比较复杂的操作啊你先把x=0写过去没问题然后ClientA把X1等于写过去没有问题然后ClientB进行了一个X2的操作,然后返回了1这个是没有问题的,你没有违反这个Linearability,是吧,就是假设它是一个DataSingle Database,它确实是一个Single Database然后呢你Client C呢又进X2的操作也返回了11这个也是没有违反Linearability的然后你这块进行了compared set 把x设置成2了没有违反Lineability,然后进行读,读出来是2,没有违反Lineability,然后你这块进行了一个Comparset,然后你进行读,然后X等于2然后这块是没有影响Linearability,但是你这块如果读出x=0的话,那你其实是违反了Linearability,因为你这个时候x应该不等于0了。是吧所以你这个操作应该Arrow的,但如果这个操作过去的话,通过的话,那你其实是违反Linearability的。因为你是先是x=2,然后又revert back to x=0了。然后这块的话,set成了x=4,然后你有个读,然后这个读的话,返回来x=4。然后最后再有个读,然后说x=2,那这个是违反Linearability的因为这个x等于4已经返回了,并且这个x等于2的毒是严格的strictly after x等于4的这个x=2的读是strictly after x=4的,所以这个是影响这个linearity的。假设我们把x=2的读往前拖一点,就是这个更前一点,拖到这个位置。我看我能不能画一下嗯我尝试一下我看能不能画一下啊可以笑一下好我们假设这个呢,RAID是从这开始的甚至不需要那么多对是能不需要这么多只要从这开始的那么它是不违反 Linear Ability 的为什么呢 因为它这个读的时间呢可能会在这儿这个是他读的时间所以他在这读的话他确实等于2对吧,它如果在这读的话,它确实等于2,然后等于4,所以如果读的操作时间再长点的话,它是不违反linearability的。但是正是因为读呢,就是它这块有时间,所以是strictly after x 等于4,所以说他在x等于4读到以后又读到x等于2所以他是违反linearability的不知道有没有解决大家的疑惑相对来说这块逻辑是比较复杂的如果我们high level的说一下,就是说linearability是什么意思呢?linearability就是你有多个database,然后多个database有多个replication但是你对多个Diabase进行操作的时候就是一个是读一个写的是操作你可以投影到就是project到一个database上就假设就像只有一个database在处理所有的读和写操作你刚写入的值能被读到那就是recency guarantee,那就是lineability像这种情况下,当你argue一个系统是不是满足Linearability的时候,你只要有一种time scenario,只要有一种scenario它是在 Linearability Guarantee 情况下可能会出现那它就是满足 Linearability 的如果不存在这种 scenario 一定不存在的话那它就是Valid Linearability的然后对于Distribute System来说的话,因为它这个执行时间太快,并且它执行的scenario特别多所以任何可能出现的Case,给它足够长的时间就一定会出现,就像我们之前说的就是经常讲的一个很有趣的一个概念,就是说,如果给一个computer来不停的random print character 的话Random Print Character 给它足够长的时间,它总是能打出一个莎士比亚的作品,全部可以打出来的。这就是一个概率问题,给它足够的时间的话,即使是一个Random Output的一个Computer,也可以打出莎士比亚的作品。然后另一个概念就是一个概念就是说,假设你是一个随机漫步的人,在一个二维二Dimensional的一个2D就是一个平面实际漫步的一个人那么给足够长的时间你一定会回到原点在两维平面随机面部的人在给足够长时间一定会回到原点对三文是不敢听的,就是3 dimension的话,如果你是能上下左右前后走的话你是不能guarantee回到原点,这就是数据证明的但是如果是个两维平面的话,你是一定能回到原点的。这块一样的,就是理论上能出现的这个值,给时间足够长,它在这个Compure System中一定会出现的,特别如果给这个Distribute System打交道很多的话,它会一定会出现的。然后有人问说这会儿为什么B读的是2?他可能读的是个replica 是吧?如果你读那个 [20:00] Timerray的话应该读的是4但你如果读 Replica 的话可能就读的是 2 的所以他读这 2 的可能 2 的很有可能是读了一个 Replica 因为这个 Database 它不是一个一个database 如果是一个database的话就没有lineability什么事了是吧它肯定是多个database,然后多个database前有多个replication什么的好,我们看下一节我现在就把这个插掉谢谢大家嗯我怎么要把它擦掉呢? EraserOKOK 好 然后我们接着看,就是说,这边的话,LinearAbility这块的话然后它这块的话就是简单解释了不同的之前的那个replication就是single leader replication能不能实现Lineabilitysingle leader replication呢是可以potentially实现Lineability的这个是可以实践的,它需要进行一些优化然后因为我们思考一下这个Single Linder的这个Replication它本身是有Linearability的潜质的,因为它只有一个Single Linder,然后它所有的这个所有的log是可以从这个leader来进行发的,他把这个所有的这个replication log 发给所有的 follower然后 follower strictly follow replication log所以它是有实践 linear ability 的潜质的然后我们读的时候,我们读的时候就只要从这个leader上读的话,那它就是满足linearity的。或者是我们把它变成一个synchronized replication,那不管是从leader上读还是从follow上读,只要你不是read on committed的话,你都是有linearity的。然后,Consensus和Linearability是同一个概念,Consensus和Linearability是同一个概念,如果我们分的更细一点的话,Consensus应该是Linearability的Compare的Set,所以Lineability的Comparset和Consensus是同一个概念的,最终是等价的对于Multi-Leader Replication来说,它是不存在Linearability的,这个的话也是比较好证明的。为什么 multi-leader replication 不存在 linear ability 的?因为你你读不管是读Leader A还是B,你得错值是不一样的,是吧?它本身就是不同的server,并且这两个server之间是没有交互的,短时间内是没有交互的,它eventually会 consistenteventually will resolve the conflict但是一开始的时候他们是有conflict的所以他们之间是不满足Linearability的然后这个Leaderless replication是不是Linearability呢如果你是要看Denimal,Denimal说它是Linearability的,所以我们就说那个,我们不是上一次讲那个就是Uber的这个Payment怎么做的,它是用了Denimal的Linearability Guarantee,是吧?他们说他们是Linearability的,当然这块的话可能会各种Counter Case,各种Counter Case出来,它这个可能我觉得还是一个学术研究问题啊,就是看起来更不像是 Linearability,只不过它出现 Linearability violation 的概率很低,是吧?你可能得想一种非常奇怪的 scenario然后才能会出现违反 Linearability Guarantee 但是看起来更像是不是 Linearability 的然后这个书里面也画了大量篇幅解释为什么不是 Linearability 的但是这块很难arguer的一点就是其实Linearability本身就是一个非常复杂的概念,就是你的这个age case, risk condition 挺难找并且你早见了以后,你可能很快就fix掉,是吧?如果你早见一个Linearability,说它不是Linearability,很快就fix掉了。但是还有可能出现更多的risk condition,它这个risk condition可能是无穷无际的risk condition,是吧?你没办法从逻辑上证明它是Linearability的,那很有可能就不是Linearability,是吧?我记得好像Ross,我那天跟Ross聊,Ross也说他们这个payment里面用DynamoDB做payment,做这个payment好像确实出现一种比较weird的scenario就没法解释这个payment的为什么loss很多时候这个DynamoDB确实确实就是它那个比较confusing,特别是Lineability 这块比较confusing,所有的Race Condition 都可能出现好,最后我们说这个Linearability的Cost是什么,就是有人写PayPal证明过Linearability的Cost through Network Delay所以你的Linearability的这个就是你的Linearability的cost就是时间cost有proportional就是你的proportional to network delay这个是proportional的好然后最后一点的话就是这个CAP,我觉得相对来说,consensus algorithm,包括就consistent里面最有名的一个说法就是consistency availability partition 里面三个选两个,但是这个说法是不对的,这里面的 consistency 其实就是 linear ability其实讲就是Linearability,表示是Linearability的意思。这个说法是不对的就是因为这里面consistent [25:00] availability是你设计中可以选的但是partition它是一个fault它是一个一定会发生的事情就是partition是一定会发生的事情所以你其实是没法处死partition的因为你如果是做一个operating的话你比如说你要operate一个data centerpartition不是你能选的事情partition是一个fault给它足够长的时间partition是一定会发生的所以说给它足够长时间莎士比亚作品是一定能被水机写出来的是吧或者给它足够长时间你一定会走回一个二维平面的原点的所以这个partition你是不能假设的所以更多时候这个CAP它不满足的这个条件就是CAT这个就是你三条不能同时满足你应该这么解释就是说如果发生partition的话你是想要lineability你是想要consistency还是就是你想要consistency还是想要availability就是如果发生partition的话你是想要availability还是要consistency如果你想要availability的话,就是这个Denimal这样设计的我短时间内不consistent,无所谓,像Denimal的整个设计就是maximum availability 去设计它也是被 CAP inspired 的它就是maximum availability 去设计的如果你发生 partition 的话你去 lean over to consistency或者 linear ability 的话那你其实就是传统的 db还有包括这个传统的这个 two-phase commit 这种是吧用 two-phase commit 的这种就是 guarantee 这个 transaction当发生 partition 的时候我这系统就不 work 了不 available 了但是我的 consistency是有 strongest guarantee 的所以这个解释distribute system中一个设计,就是这个CAP解释的时候,就是说你不能同时选C和A,因为partition的发生是你不能控制的,所以你不能同时选C和A就简单问一个问题就是partition tolerance在这里是到底是指就是在一个系统里面任何两个node之间就是它可能会存在就是Network Delay还是指任何一个机器可能会挂掉这块的话这个partition tolerance的话好问题其实其实您可以这么想就是delay和挂掉是没有本质区别的你如果这个delaydelay了100天那你和挂掉是没有本质区别的但是computer sense这个里面你delay一个小时那和挂掉本质也没有区别的所以后面说的consensus algorithmdelay了就相当于是挂掉了基本上consensus algorithm的设置delay就等于挂掉它是不区分这两者的然后其次你一个node的挂掉和你和这个node发生了partition和其他所有的node分隔开其实也是没有本质区别的对吧你一个node挂掉了就是一个node挂掉或几个node挂掉和这几个node的和剩下的network发生的partition也没有本质区别从这个系统的观察角度来讲是一样的是吧但是有一种是有区别的就是如果你有就是比如说你有一个network然后你分成一半是吧然后一半是一半在线一半不在线不是你有一个network然后把它从中间切一半是吧平均切一半然后其中任何一半都没有任何offline但是这两半之间是没法相互沟通的那其实的话这种是比较一个特殊的存在这种情况下的话你其实任何一个partition就是任何你吃两个partition任何一个partition可能都是equal weight的那你可能会有各种conflict就没法去用这个多数来决定去resolve了这种情况可能稍微比较特殊一点不知道解决你的问题对对 我觉得是理解所以在distribute system 里面 我再强调一下在distribute system 里面 特别在考虑consensus的时候Network delay 和这个node的挂掉是没有本质区别的然后这个node的挂掉呢和这个partition 呢就是这个node会被partition掉了是有点区别的但是其实相对来说区别也不是那么大的对的所以这个如果从严格角度来讲的话你可以认为是这个node可能发生node的挂掉或者是network挂掉就是它link挂掉然后link挂掉的话就被partition了但是如果它这个link你可能会挂得更细一点有node然后有这个age然后你在certainage挂掉以后然后可能就会出现partition但是很多时候,比如说你两个cluster之间还有一个link相互连的话,其实也没有partation至少两个cluster之间还有一个link在连着,也没有partation所以CAP理论,比如说在实际上面应用,比如说master slave这种模式,比如像mysapl这种情况下 [30:00] 就假设是master down掉的时候你是没有availability,就是写的availability,真的就没有了对,其实就牺牲了availability,如果你想要availability的话,你要promote一个slave变成master当你promote slave 变成 master 的时候,就牺牲了 consistency当你promote的slave变成master的时候,你就牺牲了consistency,所以这个是个trade-off啊我不太懂 就是我肯定得要promote,假设一个机器,master down了,我肯定需要failover,对吧?没有,你可以不promote,你可以等master回来以后再serve,如果你不promote的话,你data是strongly consistent的,就是给他足够长的时间,你的master和slave是data 是 consistent 的对吧如果你不promote的话但你没有availability了吗但读的availability还是有的对吧你有读的availability但是没有写的就是availability吗但是如果你promote的话,你data是一定会inconsistent的的,因为depends on你是synchronized replicate还是asynchronized replicate,如果是Asynchronized Replicated的话,其实你的Master or Steel本来就会有discrepancy,然后当你在写新的data的时候,你之前的data可能都要discarded,可能都有data loss谢谢大家哦然后如果你是Synchronized Replicated,其实你本身就牺牲了一些Availability,因为你Synchronized,你整个这个时间会更长一点,就是你每一个Transaction消耗的时间会更长一点那你其实多少也是生了点availability吗谢谢大家OK谢谢大家如果是Synchronize Replicate的话,然后Synchronize Replicate的话,如果MasterDone,这个是Lintens增加的,如果是Lintens增加的话,其实这个哦你在 certain 之后的话,reacted 也是受影响的。但是这个 CEP 好像不是这么解释的,CEP 这个里面是,这个不是这么解释的,更多时候解释的就是说,在Asynchronize 啊,或者是这种它是非常general的一个解释,非常general的一个解释就是这两个没法一直保存,如果你要 strong consistency 的话或者你这个Linearability要guarantee的话那availability总是要受影响特别在发生partition的时候对了解一点,然后我其实想问的就是比如说DynamoDB也好,然后你选比如像MySQL就好,就为什么我们通常说DynamoDB是Preference Availability,然后比如说SQL这种是比较偏向于consistency,就具体到底是怎么比较,就是这个tadeoff到底发生在哪里首先我们先说为什么Sycle是prefer linear ability,就是我们不要用consistency, consistency比较confusing因为SQL设计的时候,它就是为Linearability设计的就是它设计的时候就是它transaction 当你写sicle rule 它这个transaction 其实就是如果对于single object 来说就基本上就guarantee 了nearability特别是这个two-phase log已经guarantee linear ability了所以当你用Sycle的时候,你的那个Consistency其实是很好的,但是你的Availability呢相对来说没有对availability进行优化然后我们为什么说这个Cassandra或DynamoDB是满足了AP呢?因为如果你看Cassandra那篇paper的话他从始至终他设计的这个priority就是availability所以不管是这个sloppy,sloppy,chorum,pinted,handoff啊他所有的设计的根本的原因就是为了availability包括这个chorum整个靠着我们设计的思路的这个原因就是为了 availability所以它这个好所以它这个设计的理念就是为了availability来设计的,它也是被CAP所inspired的,就是说我们需要不需要那么strong的consistency database,我们如果牺牲点consistency的话,那我们能不能保证我们的service永远不offline谢谢大家所以我不知道有没有解决你的问题就说解决了对谢谢大家谢谢大家所以,CAP 概念是2000年左右提出的,它提出来的概念就是鼓励database设计方,希望database设计方是什么呢?能多考虑一下其他的 possibility而不是只focus on linear-billage,因为当时2000年的时候,我们可以想一下这3PO system其实没有那么多吗?一会儿刚有这个就是这个Napster 就是刚刚这个peer-to-peer system 那会还是盗版音乐这种Peer to peer system,那会儿刚好这个东西其实它这个Distribute System 虽然更早 [35:00] 就有了 但是它其实这个大家focus还是在consistency,你设计这个系统还是为了这个Bank的Transaction设计的所以他当时提出这个理念就是说我们要不要额外考虑一下Vilibility不是所有的不是所有的这个database上的这个operation都是transaction 是吧?没必要一直guarantee consistency所以是有了这个database的设计力实际上你看的话我记得这个就是cafka这个conference里面的cafka founders写过一些blog说当时为什么设计cafka是因为他们观察到他们在linkedin的时候cafka是linkedin就是从linkedin的engineer设计出来他们在LinkedIn的时候发现99%的这个99%的这个Log和这个Datadata操作吧,data operation都不是transactionTransaction只占了不到1%那如果你transaction占了不到1%的话,那么我们是不是不需要把所有东西都变成transaction?那我们是不是可以牺牲一点consistency?我们是不是可以牺牲一点durability?然后做这个optimize down这个speed 是吧所以他们就设计了这个这个 Kafka 的 login system 是吧?就是你如果不是一个 transaction 的话就走 Kafka 全就行了 是吧?然后 Kafka 在这个再接一个SUNC,然后再存到什么其他地方然后为做Analysis,就是Offline Analysis,或者是Analytic Analysis但是你其实如果你不是Transactional Data的话你是不是可以用卡夫卡就放到卡夫卡里面就可以了正是因为有这样的想法,就是卡夫卡为什么被发明了,后面他想了各种什么event driven好像相对来说都是之后了吧就是之后的这个Event-Draven concept 然后后面to share把他写了卡夫卡里面但是他之前的话其实就想一个写一个比较 efficient 的 systemEfficient system 怎么样处理各种不是 transaction 的一个 data operation所以, again, Cassandra 就是为 Availability 设计的,所以它肯定提供 Availability 更好一点。所以我们读 Cassandra, Dinamo DB 这个 paper 的时候,它从事之中强调 Availability 。当它做 trade-off 的时候,因为它的go就是为了提高availability,所以它所有的tradeoff都是提高availability进行设计的。好我们看下早Total order replication, Total order and Partial order, this is a theory of a theory of a theory.你比如说A和B和B和C之间是没法进行排序的事吧,或者是A和B和B和C之间是没法进行排序的事吧,嗯因为它本身是没有等价的排列的价值嘛,就是没法进行排列的价值但是有些东西是可以partially order的,比如说多个operation比如说在Gate里面,GitHub里面,你有多个Branch,是吧?然后你最后有一个Master Branch,然后多个Branch merge到Master,是吧?最后eventually merge到Master,那么在两个多个Branch之间,这两个多个Concurrent Branch之间,你是没办法进行排序的但你最后merger的master是在这个多个brunch之后的,所以说你这个其实是个partial order这个pass order更多像一个就是有点像DAG 如果你把Parture Order画出来的话就是DAJ Graph然后你可以把它画成一个DA对管Total order更像一个link list,是吧?就是一个list,然后它之前的就是发生在前,然后之后就是发生在后所以我们如果从这个角度来看的话Linearability的cost还是太高,因为Linearability的cost和Lightwork和Lintensive的cost是一致的很多时候Linear Ability, Linear Ability 就是 Total Order, 是吧,我们把所有的 Operations把它一个一个拼到一个 single database 上,所以 Linearability 就是Total Ordered Operation但是很多时候,我们其实不需要知道Total Order的Operation,比如说我们思考一下在Database里面做那个Serialization的时候,如果有多个 concurrent transaction最后只要它是concurrent,它以什么样的先后顺序进行commit,其实我并不care反正它们都是Partial Order嘛就是你有多个Concarned的Transaction你最后这个A和B是concure的,A在前还是B在前,我们并不care,假设是这个假设是没有conflict的那你A在前和B在前我并不care那最后的话从database的角度我是有个total order的但是我们这个total order不管是AB还是BA从Database的角度是无所谓的虽然你最后有个Total Order但是从Database的角度是无所谓的所以 [40:00] So the concurrent operation, What is it? What is it? What is it? What is it? What is it? What is it? It's not a casual order. Partial order. What is it? So we often have a consistent distribution system in the distribution system. We don't have to seek total order. We only have a casualty guarantee. We can use partial order. So this is Lampod. This is Lampod. It is a very long time ago. It was a very long time ago. Lampod is a Lampod time stamp. What is this? In the database, we said in the database In the distributed system, the clock is It's not a high level. Your device A clock and your device B clock can be compared to the same. Lampod says, how can I set a reliable time? Can I do this casualty? Can I do this in the time stamp? So Lampod is set a time stamp. What is this time stamp? It means that you have every time stamp with your device. It is actually a logical time stamp. It's not a total time, because it's a relative concept. It's more than a time. It's a logical timestamp, so it's a logical time stamp. So in this timestamp, in this system, you have a time stamp. One is your node number, and one is your event sequence. So let's look at the node number 2. It's a simple way. You have the first event, so you have the counter is 1, the timestamp is 1. Then you have the second event, you have the timestamp to become 2, and the third event is the timestamp to become 3, and the fourth event is the timestamp to become 4. But this time you have a client from the other client. And this client, The max is 1, right? You can see the client request max is 1, and the local max is 4. Then you should return to the two points, so you return to the 5. And then after the request, because you've already written it, you have to write it in 6. that we do any node 2. He has any request for it is sequence. So in Node 2, the request is sequence. So the logic of the relationship is 2 at 3, 3 at 4, 4 at 5, 5 at 6. For the node 2, it is a sequence. And then we'll see node 1. Node 1, it was written in the first time. This one is in any time. So this 1, this 1 is the time stamp 1. It may occur in this This Node 2 of 1, it may be found in Node 2 and 4 of 1, it may be possible He wrote it again, because Klant said that the most small number of the number is 1, You have to write the next one in the second one. So the next one is written to the node 2. Then the next one is written to the node 2. So client A says, I write the sequence 5. I don't know the sequence in the next one is written to the node. The sequence in the next one is written to the node 5. So when he wrote this node 1, the sequence of node 1 will bump into 6. So we'll see this two of them. From node 1's perspective here, It is also a casual order. Why do it have casual order? In the first step, the small time stamp will be in the back, the small time stamp will be in the back, the small time stamp will be in the back, this is guaranteed. But in the cross node comparison, How do we do it? CrossNode's time stamp configuration is that your large time stamp is guaranteed to be bigger than the small time stamp. If these two timestamps are the same, you can decide who is the same. Because from this time frame of view Operation 1 and Operation 1,2,3次 are concurrently happening. Operation E2, Sensor Concurrent, is a operation E2, Sensor Concurrent, is a operation of the concurrent. So you can put it into any time, any time is making sense, not to violate the operation. and not valid concurrent linear ability But when we set up the design, we need to ask that if these two timestamps are not the same, Time stamp is the same thing. Time stamp is big, and it is happening in different devices. So in this case, it thinks that all the 2, 3, 4 events are happening in node 1 and time stamp 1. Although this is probably possible in time, in time, is possible. [45:00] Time-Time就这么设计了是吧,因为你没有一个你没有一个sauce of truth 告诉你说它到底在发生什么时候,那么我就用 time stamp 来比较。如果timestamp相同,那就用node number来比较。所以最后比较的结果就是这个Node1,TimeStamp1是在CIS所有的Event发生之前但是当它有一个cross node operation的时候,这两个timestamp相对来说就进行了一个sync之外。从这个节点之后呢从这几点之后呢,我们就知道这个Node11是一定发生在这个Node26之后的,是吧?就是这个不管是从它timestamp设计还是这个时间设计,一定发生在这个之后的,然后这个这个这个其实是,我们说这个其实是提供了一个什么呢?是把这个LampPod的timestamp是提供了一个unambiguous concurrency, ambiguous concurrent timestamp comparing tool.然后他Guaranteen the casual order is not violated我们用这个重新rephrase解释一下,就是说LinePod的TimeStamp是guarantee什么呢?多个Machine之间它的开入Time Stamp是没有被violated的它的Safety Guarantee没有被violated的就是你这个Time Stamp之间你用Lamp Power Time Stamp进行对比你的carot dependency是没有被violeted你是有carity guarantee的但是它到底是不是按你的order来进行发声呢有可能不是,就是如果你有一个Oracle,有一个先知的人物看这个全局这个事情发生的前后的话,它可能不是按那个lampod的timestamp这个order来发生的。但是它guarantee你的casual order没有被validated这是这个Lample Timestamp我们看见LampoutTimeTime其实是不能满足所有东西的,比如说比如说,我们现在同时有两台机器,说我要生存一个域名,我要生存Uber.com,或者我要生存Google.com,我要生存这个域名,那么你看到的时候,当你用Lambport的timestamp来进行order的时候,你已经是after effect,就是你事后才知道谁在前谁在后但你在当时的时候,你不知道有没有其他Node同时在声称Google.com这个域名,是吧?所以这个Lampout Timestamp这个Lanport的蓝博特时间Lanport time呢它只能做一个audit也就是说它可以事后追查实在前实在后但是它是没办法当时做出决定实在前实在后的所以这个呢,Lambop Timestamp是不能guarantee就是你不能解决这个 concurrent 的问题,你也不能解决这个 total order broadcast 的问题,或 linear ability 的问题,或 consensus 的问题因为它设计是不够的,就是它这个设计是不够解决的consensus问题的然后这块有一些论证解释为什么Total Order Broadcast是等于compared center linear ability等于consensus我们这块就略过了,就是它这个论证也是比较复杂的,有点证明这个NP问题为什么是整价的感觉。相对比较复杂的 我计划还是略够了 因为这张确实如果你不自己去读的话我觉得我只能给大家提到一点 就是启发大家去读 这张的话还是要需要大家自己去读才能理解这个Consensus它确实是比较复杂的简单解释一下,这三个问题是相互等价的。Total Order Broadcast是什么意思呢?Total Order Broadcast是什么意思呢?就是你首先要guaranteereliable delivery,就是你在broadcast的时候没有任何一个message丢失了如果一个Message deliver到一个Node,那它应该delive到所有Node,就是All Nothing没有Message Loss然后其次的话,你所有的Message的Order是guarantee的。你这个order是1234的话,那你所有的其他node的order应该是1234。其实这个totalorder broadcast就是synchronized replication,就是replication。就是 replication, total order broadcast,就是 synchronized replication是你用replication log 来实践它是一样的嘛,就是你synchronize replication 什么的,就是你database 当且紧张,所有的master和slave都说我收到这个交易并且有这个transactiondeliver到所有的slip上了,那我才返回OK是吧,那我的所有的这个,那这种情况下呢,你其实没有message loss嘛,其次的话呢,你的message order也是一致的如果你们order不一致的话 你可能会有一些set effect 是吧replication log的话是 这个order是要guarantee一致的 否则的话你会有set effect所以这个Total Order Broadcast 其实就是Synchronizedreplication 许可信号: single leader synchronized replication是一系列的,一系列的 [50:00] analyze the replication. Compare the set linear ability is linear ability guarantee. It is the linear ability guarantee. It is the final point of consensus. What is consistency? We talked about consistency, and we talked about Uh. Two-phase commit. Okay, let's talk about two-phase commit. We have two stages in two phases. I'm going to look at this one. This is the two-phase commit. This is the two-phase commit. The leader election and atomic commit. This is the case. This is a question about the total order broadcast and consensus between the two sides. In this case, the total order broadcast is how 等下于 single leader. replication And this one has a two-phase commit problem. If you are in several devices, you can commit to the commit. If you want to ensure more data is consistent, you can be able to make more nodes. Commit, For example, let's give a simple example. When you do a transaction, you can do A and B at the same time. But because of partition, A and B are in different partition. I'll give you a example You can say For example, the most famous example is when you were in transaction, you modified data, and you used global secondary index. You use Global Secondary Index. If you want your index to your transactions, you can also be committed to the same. Then you use Global Secondary Index. Your index and your data are similar. 90% is not in the same node. not in the same partition. The guarantee is not in the same partition. If you want your index If you have the data, the index will be changed, then you need an atomic commit. The data update and index update is the same. In the database system, there is a two-phase commit. If you are on distributed systems, the first big big thing is to create a two-phase commit. I remember when I was on the distribution system, When I was on the DISTRIBUTION SYSTEM, my first big job was to do two-phase commit. And in the two-phase commit, it's a bit like this It's a bit like a proposal, like a proposal. First of all, you have a coordinator. The coordinator is a bit like a teacher. Then you have database 1 and database 2. Database 1 can be considered as a new man. Database 2 can be considered as a new man. And when you say this, you say this coordinator, you first say you're a marriage, you're a marriage, and you're a marriage. And you're going to give two of them a marriage. and it表示 that this thing you agreed. You know the context is what? In the database, the coordinator will also write the data in the database 1 and the database 2. Guarantee is that it will be more than the database. The "结婚" means that it's not the database. The coordinator will also write the data in the database. It will ensure that the data is completed. But it will not commit. Then, the time This is the case for the case. The coordinator is the teacher. The teacher will say, "A, you want to marry with B?" and "A" will answer. And if you have any reason to say no, you can answer no, that's the whole relationship of the relationship. About 掉了, but if you decide to do it, I would like to do it for you. Then you say yes. When you say yes, when you commit yes, you can say no. you can't be able to do this. To face commit, any situation can be able to do this. You can ask B, "B, you want to do this?" If you want to do this, you can't be able to do this. If you want to do this, you can't be able to do this. If the teacher is the same, he says, "The situation is completed, and this is already done, so the commit point is what is the same?" and then he has a proposal to commit. If the teacher has a proposal, he has a proposal to commit. If the teacher has a proposal, he has a proposal to commit. [55:00] 同意A和B结婚这个事已经写到小本子上了然后A和B回来看的时候确实看到结婚这个事情通过了他们已经成为合法夫妇了这个是有一个atomic commit point就是牧师把这个事写到小本本上对应的就是这个coordinator把这个Commit log写到disk上这是一个atomic point在这个atomic point之前整个这个transaction是在多个database上没有committed在这个atomic point之后这个transaction是在这个database上committed的那么其实这个逻辑是比较简单的但是这个复杂点是什么呢复杂点是可能会发生各种failure是吧比如说有什么failure呢比如说我新郎和新娘说愿意互相嫁给对方就committed yes了然后这时候找不见牧师了牧师突然消失掉了被外星人绑走了那到底牧师有没有把它记录到小本子上牧师有没有把这个结婚的事情公正下来那其实是没有人知道的因为这个牧师当掉了那这种情况下呢新郎和新娘呢就是这个node1和node2呢都是不可以about这个transaction的因为当你回答yes的时候你就不停的要等就直到等到这个牧师online所以你是不可以about的你知道吧就是你必须知道这个牧师当时有没有记录下来有没有记录到小本上然后他有没有记录完整的完整的记录到小本上是吧如果完整记录到小本上然后你就是表示合法夫妻如果没有的话那就是表示这个结婚这个仪式还没有通过是吧所以就是说如果是这个就是这两个人回答yes以后这两个database回答yes以后这块是很有可能会发生死索的就是你这个不叫死索不叫dialog但是很有可能会stuck在这边为什么会stuck在这边就是coordinator状态不可知coordinator状态不可知所以coordinator没通知他们中的任何一个人所以他这个fill他这个coordinator failure point和commit point所以可能会出现思索的状态好,然后还有一些其他的简单的scenario比如说这个coordinator就是这个node fill了node在write data之前fuel了node在prepare之前fuel了那这个coordinator的任务相对比较简单了我就可以报的就可以了反正您可以认为是这个律师连结婚誓言都没有读文然后其中一个是新郎不想读文就是这个设计的设计就是这个设虑的任务相对比较简单了我就可以报了就可以了反正就是你可以认为是这个律师连这个结婚试验都没有读完然后其中一个是新郎新郎跑掉了是吧那你结婚礼就举行不成了或者是律师读完这个结婚试验了就是这个data写进去了但是他没有问就是他没有就是他问那个你是不是有愿意嫁给他什么时候然后那个新郎新娘又挂掉了是吧那也可以终止是吧等他回过来的时候再说是吧所以这个是可以用这个结婚仪式来进行解释的我觉得也比较有趣的你确实可以用结婚仪式进行对比一下这块有一点非常有趣的一点就是如果两个人进行committed就是这个node进行committed以后他是要在不顾一切的情况下来是一定要知道结果的不管是yes还是no 他一定要知道结果的并且这个结果是只有coordinator知道的你没法从另一个人身上知道这个结果如果这个Coordinator在这个之后在他回答你们到底有没有结婚之前挂掉了并且永远没有online的话那你这个结果永远是不可知的那你Database1和Database2这个Transaction是永远卡在这里的所以他不可以接受其他的Transaction他是不可以接受其他Transaction的因为它的其他Transaction如果和这个Transaction有Data Conflict 的话那它这个其他Transaction就被Block 掉了因为你如果写了Data你就Violet的誓言了是吧举个例子就是新郎和新郎表示可以什么可以就是都同意了是吧然后律师跑路了是吧律师跑路的话那你这种情况下新郎和新郎是不可以接受再嫁给其他人是吧因为你不知道这个当前的结婚仪式完成了没有所以就永远卡在那里了所以我们就说为什么说这个two-faced commit的在这个no turning point就是在这个commit的这个以后呢它其实这个performance是极其糟糕的就是有一种scenario就是当你的coordinator挂掉了以后你的performance会极其糟糕因为你很有可能有一个transaction所有人都回答了yes所有人都回答这个transaction回答了yes但是你的Cordination挂掉了那你这个Transaction就block掉了你整个Transaction就blocked伴随block是你这个TransactionTouch的Data就全部被lock住了那就没有人知道结果了好 这块的话我也是cover了这个律师挂掉的这个scenario所以这个Two-Face Commit [60:00] 这个 performance是比单独的Transaction Performance要慢一个数量级的,甚至很多时候要慢多个数量级。我们之前讨论过就是说,当你有一个single node的时候,就是你一个single node现在每秒就能handle10^5^2的Transaction如果你用2-phase commit的话,你可能每秒钟只能handle 1000 次 transaction,甚至是 100 次 transaction,差这么多,差一个数量级到两个数量级,并且如果你出现这种 coordinator failure的话,当你出现这个Coordinator failure,当你律师在最后公正的时候跑路的时候,你其实机器是没法解决的,你必须用人为的来解决。所以这个 two-phase commit 为什么不喜欢被人用?大家为什么不想用 two-phase commit 的原因?就是performance 实在太差了,差一百倍了你一秒钟只能 handle 100 个 transaction好,然后我们最后看一下这个Consensus这块Consensus呢它其实是多个要求吧我们看一下什么样的algorithm是满足Consensus的首先Consensus就是语义来讲是所有人都agree on the same thing,是吧?你就说比如说,我们说这个到底是中国发达还是美国发达,是吧?到底是这个TikTok更有趣还是Facebook更有趣,是吧?你要agree on the same thing,是吧?就是你有uniform agreement,你不会说A觉得中国发达,B觉得美国发达,是吧?然后A觉得TikTok好玩,B觉得Facebook好玩。就是你所有人必须要决定同一个东西上。然后integrate什么意思呢?你做出的决定你不能反悔你比如说你做错决定说我打算今天去吃麦当劳是吧你就不能反悔说我今天去吃肯德基,你只能做一次决定。你不做两次决定,你作为一个 decision,你只做一次决定,作为一个 node 来说validate什么意思呢意思说当你决定Ada Shahal就是当你决定A的时候,A是其他no的proposed的不是不是一个凭空来的value如果没有这个validate的话,其实这个consensus设计比较简单,所有node都同意是0就可以了,是吧?你不管propose什么值,所有node的propose是0,那你是有consistency的,是吧?你是有consensus的,你说node返回0的话,你是有consensus的,但是你这个0可能不是其他node的propose的值,虽然你agree 0 但是 0 可能不是Channel的proposer 值然后最后的话是Termination 什么意思呢?就是如果你没有Node, terminated,那你最后总是会做出就是你如果有node还活着的话你最后总是会能决定某一个value的所以说我们来看一下这个,如果我们这四个要求里面,假设你没有valid这个属性的话,假设你没有valid这个property的话那所有node就无脑的选0就可以了是吧那你这个0其他都是满足的吗就是所有node都做了一个决定就是0然后所有的Node的决定都是一样的就是0,那所有Node的只要没有挂就可以写0,无脑写0就可以了,但是它是不valid的,所以是不满足consensus的。然后如果没有termination的话,那我们刚才讨论的two-phase commit呢,是满足这个consensus的。什么意思呢就是说我们所有的这个node呢都是agree同一个东西的或者是Single Leader Replication是满足没有Termination的Consensus的所有的Node都是决定同一个东西的,因为它有Master决定就可以了然后没有一个node需要决定两次,因为master决定一次以后就可以push到slave上了然后其次的话,Master的决定值可以是它Propose的值嘛。所以这三项都是没有满足的,都是满足的。但是这个Single Node的Replication是不满足最后一项的。为什么不满足最后一项呢?是因为如果master crash掉,slave没有crash掉的话,那consensus要求是slave之间应该是要决定一个值的,但是这个single node replication呢,就是Single Node Replication这个模式呢Master Seals这个模式呢是没法而guarantee最后一项的就是Termination是没法而guarantee的好,然后我这块的话可能不花那么多时间,我其实给了一个RAFT的一个实践方式我们可以在这看一下这个里面的话就是,我们看一下这个,就是这块有个algorithm也很好,叫我今天又读了一遍,就是这个FreeCodeCamp的这个Graph的这个Consensus Algorithm时间方式。现在已有的主要的Consensus Algorithm,相对来说比较固定的有几个吧,一个比较有名的就是这个,LanPod提供的这个LanPod proposed的这个哦Pethos是LanPod提供的,但LanPod的这个方式 [65:00] Pexels其实是比较复杂的Pexels推出了这么多年以后Lanpot写了很多简化版的Pexels其实Lanpot发了很多论文我记得我还读过一个就是他写了一个简化的论文就是这个论文的目的就是为了解释Pexels给其他人解释Pexels的然后就说明这个algorithm真的理解起来比较难然后Pexels呢是因为他理解起来比较难Countercase比较多然后在13年的时候12年的时候就是这个Stanford的就是这个Professor呢就写了一个比较简化易懂的consensus algorithm叫RAFT algorithm这个其实是一二年写的然后之后的话就是之后的话第三年写了看他是获得了一四年的这家paper其实很新了其实我觉得对distributed system来说三四年新的东西基本上就是carting age了然后五六年的基本上就是业界主流了五六年的基本上业界主流了三四年新的基本上就是carting age了如果再新的话基本就是属于research范围了就不属于industry 范围了所以这个其实是非常新的一个 algorithm这个Roughed algorithmRoughed algorithm它唯一的目的就是说我其实是Paxos我其实跟Paxos是一致的但我比Paxos更好理解就是Roughed algorithm设计的目标因为它简化了这个这个里面这个leader electionfollower leader和candidate之间肉的角色它简化了这个肉的角色我们看我们简单直观看一下我们就不过可说那个algorithm那么复杂的细节了在Roughed里面每一个node呢是有一个timeout一个timeout period一般来说像这个Hbase这个timeout period设计都是几秒钟也就是说你很多时候就是七八秒钟九秒钟才timeout但有的这个timeout呢就是有的database的timeout设计时间比较短可能只有四五百毫秒三四百毫秒我好像见过最少的只有100毫秒到300毫秒就是一般来说是短timeout但是很多时候是就是像HBase设计啊是长timeout就是八九秒是九秒的一个timeout那在这个timeout之间呢就是你叫一个term knowledge叫term就是在这个选举期间呢这个期间呢你叫这个term在这个term之间你如果是leader的话那你整个这个term之间你都是leader那如果这个term在这个term之内呢然后你可以不停地去refresh你的term是吧你可以不停地通过这个你可以不停地通过这个这个ping point是吧refresh的term然后当你当你算了这个heartbeat的时候这个heartbeat你就把你的term给refresh掉了我们看到这个是时间是1%我们可以稍微看快点对吧看快点的话实际上稍微再快点的话它实际上很多时候它这个当它没有refresh的时候当这个sr没有refresh可能whatever reason可能是timeout可能是这个srfill的话那它就不是leader了那他需要去propose一个新的term然后propose一个新的term会有一个新的leader然后当他这个leader fill掉的时候就当他leader fill掉的时候你会有一个新的followerpropose自己为candidate然后当主要的candidate决定他是follower的时候主要的candidate同意他是leader的时候那这个刚才的follower就变成了leader像刚才我们非常快的快进了以后大概在15秒之后他这个是随机生成的他这个确实是一个它好像是软在你的这个browser里面的一个Roughed algorithm所以它这个是随机生存的在15秒之后我们看到在15秒之后它的leader从刚才的s2变成s5了然后它term变成4了刚才term我记得可能是1还是term2我忘了看了但现在term变成4了也就是说在term为4的时候s5变成leader了如果这时候另一个node另一个node它没有接到任何信息然后它Timeout的话它会Propose自己成新的Leader然后它会把Term变成5它会把自己的Term变成5然后它当Term变成5了以后它会跟所有的Node说我现在是新的Term换时代了我Propose我自己成为President那你们选不选我如果别人没有看到更高的Perm的话没有看到更高Term并且别人没有timeout的话他会选5作为一个新的president的话会选5进行新的leader然后这样的话他们会所有人会agree说5是新的leader那么我们要用5来作为新的leader来然后这个5会不停的发这个term5呢这个s4在term5里面是leader的话他会不停的发heartbeat然后保证其他的node是online的然后这个heartbeat也是有讲究的如果你的hardbeat太frequent的话你这个hardbeat是发的时间太frequent了我们看刚才他这个hardbeat的时间大概是大概是100毫秒到几百毫秒之间他说这个hardbeat的frequency应该是在那个paper里面的Rough的paper里面他说hardbeat的frequency应该是比timeout的时间是小一个数量 [70:00] 比如说你TimeMod是如果你Timeout是10秒的话,那你Heartbeat最高也是1秒是吧?如果你Timeout,这个Timeout如果是500毫秒的话,那你Heartbeat最高,就是你的这个Interval最高应该是50毫秒,你应该比发的比50毫秒更frequent这一点。所以当你变成leader的时候不停的发heartbeat然后这个hardbit越小呢那你就越有可能发现这个,你就越有可能subject to your network这个fault是吧,Network发生fault的时候,其实这个是Network发生delay了,其实这个node没有down,但是你认为它down了,然后就开始了新的这个是吧你的Heartbit越小,就是你的Heartbit发的越频繁,那你就有可能subject tosubject to 这个新的 election 但是你 heartbeat 发的越不频繁的话 你可能会就反应越 slow 比如说我们举个极端例子就是你 heartbeat 一秒发一次 是吧 你这个 term 是 10 秒 你 heartbeat 是一秒发一次 那么这个 node 可能在一秒之前就 down 掉了 那整个一秒它 down 的这个时间呢 是没有人被 detect 出来的 就是你没有 detect 出来这个 follower 在接下来一秒钟一直 down 的这个状态 是没有 detect 出来的所以这个是这个是你这个Hardbit的这个Sat的Tradeoff好,最后一点,我们说为什么要用Consensus?我们可以这么说好了就是当你有 leader 的时候当你有 single leader replication 而你不想把 leader进行hard code层次的leader 是吧你这个leader down掉以后你还希望有个follower进行replace 一个 leader 的话,那你就需要有这个 consensus algorithm 决定谁是新的 leader然后你就要决定自己的 leader你现在有 leader 不代表你之后有 leader你现在有 leader 的话 不代表你之后有 leader你现在 leader 你只能保证这 term 是十秒 是吧你现在Leader Term Guarantee 10秒那10秒之后谁作为新的Leader其实是要这么多distributed node进行decision的然后进行Decision的这个步骤就是在杂乱武装没有一个Single Source of Truth的时候就是没有一个Single Authority的时候在这些杂乱武装就去Build System里面让这些node自发的决定一个value,那就需要consensus如果你没有 consensus你都没办法在一堆node之间,你都没办法决定到底什么值是什么只是crack value 是吧?你node A 可能说是2,node B 可能说是3,那你是没办法进行达成一致的,所以Consensus可以认为是distribute system最本质的一个东西,就是它决定什么value是正确的value,什么value是dominant value然后其次的话Consensus可以用在什么呢?比如说可以做Membership Management,是吧?我们这块没有讨论的是,比如说我们就拿这个Rough的Algorithm来说如果这个Roughed algorithm 你这个node进行了更改怎么办如果你这个membership进行更改怎么样你现在不是S1到S5进行Roughed了你多了一个S6 你想用S6来取代的S4 是吧那你的membership改变了 那你怎么样达到consensus这个其实是需要专门讨论的就是说你比如说你的S1 S5 多了一个新的node或者减了一个新的node 会有一个node replace另一个node你怎么样达到consensus 你可能之前满足了consensus algorithm在新的这个条件下就不满足了就没有达到Consens你之前能达到Dominant的这个多数在新的条件下是没办法达成Dominant的所以这个 consensus 这个就是你用的就是很多嘛,就是你实际上是在一个district build system 里面在多个peer之间多个node之间达成没有争议的一个值做一个决定是没有争议的一个consensus的决定所以它可以用在什么呢?比如说Membership和Coordination Service比如说就是你现在一个cluster里面有多少个node属于你的member 是吧,你的cluster里面有多少个node属于memberRootkeeper就是实践了这个了因为Rootkeeper就是一个consensus algorithm的实践包括ETCD,ETCD实践的就是Roughed Alchism,我觉得ETCD好像是Roughed Alchism,还是不是我不是很确定,这块可能大家查一下,ETCD可能也是实现了一个consensus algorithm,然后它就是说当你有它的时候你可以因为它实践了consensus所以你可以用这个Rulekeeper你可以pick back onRulekeeper和etcd来implementing a membership or coordination service.所以说你可以用它来实践一个这个 service,然后Consensus也可以用来分配工作是吧当你有一大堆Works to allocate to nodes的时候,比如说这个Worker pool model,或者是当你说这个哪一个node是哪一个partition leader 是吧?比如说这个node12345是partition7的leader那么这个assignment其实是需要consensus的因为如果你没有达到consensus的话你觉得12345是partition7的leader别人觉得54321是partition7的leader [75:00] 那你的data会有crafted的所以这个assign work to nodes 也是需要consensus然后最后一点的话就是service discovery你比如说你现在要找一个user service你想知道user service 在哪一个node上或者说你给一个user1234你想知道user1234在哪个partition上那这个的话其实都是需要consensus去实践的也就是consensus的用处之一然后最后一点我想提到最后一点理论的一个知识了就是理论上来讲在一个就是network unbounded的环境下就是你network是unbounded的情况下你在node可能会有failure的情况下你是永远不可能达到consensus的就是你的consensus convergence理论上讲是无限大就是没办法达到consensus就是在network有failure的情况下是没办法达到consensus这是一个理论的paper这个paper也是比说我们看到这个algorithm更之前198几年还是1970几年就有这个paper了所以consensus的convergence可能会很慢可能会很慢 实际上我们刚才看的这个rough的algorithm如果这个S4和S5之间有一个node断掉了就是这个node之间这个connection断掉了那你很有可能就永远不conversion你可能就永远不conversion的就S4和S5不停的相互当leaderS4和S5不停的相互当leader然后做不了任何其他事情也就要那个consensu就有点像这个repartition stomp这种感觉就有点像consensus stomp的感觉就是S4和S5之间相互不停做leader然后任何事情都做不了但是更早之前就是有人从理论上证明说这个consensus很有可能是永远不converge的这个consensus如果在这个unbounded network的情况下是永远不converge好这个consensus就全部讲完了这张相对来说是比较复杂的我建议因为我自己读过这个raft的这个paper也读过这个paxos paper我建议你们读的话读raft就行了因为这个RAFT 近几年有多个实践我记得我看前两天17年的时候我看17年的时候Python是刚刚实践了一个algorithm我记得有一个叫Python-GosomPython-Gosom是那个Python的conference然后17年的时候Python有个developer实践了RAFT的algorithm像18年的时候18年最近到18年的时候Kafka他实践了RAFT的algorithm就是用RAFT做consensus,然后才把这个root paper给取代掉。总体来说这个RAFT,反正RAFT发生的时候,我是不知道这个algorithm,我当时学习Tribute System的时候,RAFT还没有很出名,但是它读起来,它确实是可读性啊,理解能力呢,相对来说这个logic其实是比这个paxels要好理解多了。Paxos非常难理解,Paper也非常晦涩难懂但Rapt相对来说,你看它这个有向转的finance machine 相对是比较好理解的然后Paxos和Rapt,它的那个就是Worth Case也不一样Paxos的Worth Case,因为它设计的缘故,它是实际上是不同的node在不同term的时候,它Worth Case就是它Worth Case在raft的话是两个node之间出现partition的时候它worst case是会出现worst case它的worst case实践的out规则不太一样但是相对来说raft也是比较新嘛然后也比较好理解所以如果你要读concenters的感兴趣的话可以读一下raft我觉得还是比较有趣的还是比较值得一读的比较商量就是比较像这个解释其实不是太商量其实我觉得你可以给一个初衷生解释清楚怎么回事但是你要是把这个所有的counter case 想一遍的话还是比较伤脑的一个过程然后大家有什么问题吗然后我可以帮助回答一下相对来之前看那个就是Cassandra那个是用Gossip就是Gossip也算是Consensus它其实Detect有没有机器当掉了Gossip它应该是做Membership Management是用Gossip吧对 是的对 Membership的话您可以认为Gossip就有点像这个了只不过它不是有一个Single Node它可能是A发到B,B发到C,C发到DGossip其实是Hardbit发的一种模式那它其实是解决一个Consensus问题吗还是有点理论没有,Gossip和Consensus不相关Gossip和Consensus不相关Sensus的逻辑是什么意思就是在任何一个时间点对于任何一个Node来说 [80:00] 你知道随时leader任何一个时间点对任何node来说,你只要是leader,可能没有leader,可能没有leader,这时候在做leader election,leader election可能会持续好几百毫秒但是这个Consensus就是任何一个设断之后知道任何一个Node谁是Leader但是这个Gossip是什么呢? Gossip是,它更多是一个data的一个spreading,就是你把这个data从S5,然后传到S4,然后S4再传到S2,然后S2传到S1,然后S5又传到S3,它是一个data的eventually consistency的一个pattern,它是一个 broadcasting pattern啊Gossip is a pattern of broadcasting. When you broadcast, for example, S5 has the latest dataS5得到最新data它可以说把自己的最新 data 同时写到S1 S2 S3 S4 是吧但是它带来的问题是对于它的这个Network压力太大了是吧它同时得写这么多它Network压力太大了很快它这个Network变成BotlNet因为我们之前讨论过很多次Network是最重要的resource在Data Center里面Network是最重要的resource它的优先级甚至高于memorageMemory CPU,CPU不值钱的,大部分时候CPU不值钱的但Network是最值钱的东西是吧所以它不能一上来就 broadcast 嘛那他broadcast的话,他对于他的Network负担太大了,那他怎么办呢?他就把S5传给S4,然后在下一个时间S4传给其他,这相当于是把这个broadcast的这个load呢,是eventually distribute到其他load上了。所以这个Gossip给他数过长的时间,他拿到最新Data是会在所有的S1到S5上达成一致的所以broadcast是gossip是broadcast的一种pattern它不是一下发给了所有的Node去Broadcast,它是这种间歇性的慢慢的进行 broadcast 然后最后的最后的目的是为了eventually consistent那我在想那个这个membership management不是就是想知道就是通过Hotbeat之间知道哪些机器是 leader 哪些机器是 leader 哪些机器那个地方是 leader 然后哪些机器已经 down 掉了 就这个 post 才应该做到的对 这块的话有两个概念这块有可能是我读的有点欠缺,我不知道是不是有人用gossip来做这个membership的这个heartbeat的我不知道有没有这么做的,但是当我们说的membership其实是两个概念,我个人理解我们说的membership是两个概念,我说的membership是是这个Consensus里面的Mendorship,就是说,你如果想作为Consensus的Participant,你想作为Consensus的这个或者你想作为Consensus的这个Leader或者是Participant你这个Membership,这个Membership是要非常快的Hardbit你说的那个Membership呢更多时候是看这个机器有没有在online 是吧这个机器有没有挂掉那个是不需要你挂掉两秒钟无所谓你挂掉三秒钟也无所谓但是你在Consensus里面这个Hardbit的话一般是几毫秒几十毫秒发一个我们可以看一下我们可以看一下我们这个现在是50分之一吗50分之一的播放数率然后一秒它差不多就是20毫秒一个Hardbeat,看到没有?它差不多就20毫秒一个hard bit 因为它是50分之一嘛,它大概是20毫秒到40毫秒一个hard bit所以说这个hardbeat呢这个consensus里面这个hardbeat呢是非常frequent的它和这个expiration,这个time range是直接相关的你说的那个gossip heartbeat呢,是detect node有没有档掉,那是不同的 heartbeat,它的go是不一样的,它都是heartbeat,但它go是不一样的,它一般来说也不会用在consensus里面。哦然后另一方面讲的话那个Cassandra的Gossip呢可是你可能在这一段时间很多时候就是为了做Data Broadcast的它设计的,我记得我没有记错的话,它设计的目的就是为了Broadcast Data的它就是说,如果一个Node去Broadcast Data,它对这个Output Link的压力太大了所以它希望用这种Gossip的方式来去Broadcast DataOK谢谢大家好谢谢大家我之前也实践过一个gossip,没有我没有实践gossip,我实践过一个heartbeat,我之前实践过一个heartbeat还是比较有气的也没有很复杂,其实没有很复杂,OK有没有什么其他 [85:00] 很解哦,Scott,我有两个问题。你的问题是那个Two Faces Commits,你刚刚只说了Coordinate,那如果是participant是怎么办的如果是他在没有发信息之前就fail了,那Coordinator他的decision是怎么样?好对,Participant的这个Fillure呢,其实Participant的Fillure也是分两个阶段,也是分两个时间就是这个可能分多个时间吧partition在RedData之后就是RedData这个phase呢failure的话这个transaction是被obot了嘛就是cordidator等这个这个participants给他answer然后他没有说到任何answer就要bought了是吧所以在Dread Data这部分是比较简单的然后在这个Prepare这部分也是比较简单的coordinator说牧师问这个牧师问新娘说你愿意嫁给新郎吗然后他没有得到回应他认为也是about了也是可以about的。然后是participant要是活过来了之后,他是在找coordinator的log看一下。哦对是怎么样对对对所以如果这种情况下比如说新娘这会儿刚说了yes然后这个yes没有到达牧师然后牧师认为是about了但是新娘不知道的话新娘可以看一下这个coordinator log然后看一下这个婚礼完成了没有是吧那如果如果还有一种情况是相对于说coldination就比较痛苦了就是这个牧师就比较痛苦了牧师收到新郎和新娘的yes然后牧师公赠完毕了然后新娘挂掉了什么新娘没反应了那牧师就不停地得聘新娘直到他活过来他就说你们婚礼完成了,知道吧?他得要不停的拼,我以为是那个participant他活过来的时候主动的哭谢谢对于这种情况下,participant也是要主动Pull的,因为participant send yes 以后,他没有多多Response,所以他也不知道目视 commit 了没有。如果是牧师,他就装导的已经把Commit写到Log里面的话,他一定得把这个Decision给发出去收到response为止他写到log以后他必须不停地通知这个database你已经完成这个transaction了他要没有收到response的话他就不停地通知他你知道吗也比较痛苦了哦,明天,明天另外一个问题就是这个Linear stability,就是你说的还是recency guarantee,但是我看到有一些discription是说recency guarantee,但是有一些discription是说只要有一个request read out most recent data,后面的request都必须得是mult.最多的那那就代表说这个第一个看到most recent data之前,这个request之前还可能有其他的request看到并不是most recent data,但是这个data其实已经right了对对,这个的话其实来说是满足Linearability的好就是Lineability就是Lineability满足不满足的你可以认为是一个理论的或者一个观察的理论上它可能不满足但是可能reproduce的概率比较低我觉得像你说的话其实是理论上它其实不满足Linearability但是你没有这个Oracle去知道它满足不满足,你只能通过观察来讲来解释吗然后Linearability如果从观察的角度来讲的话你必须有一个反例才能才能说它不满足Linearability像这个case的情况下如果这个RAID4没有发生的话,它其实是满足linear ability的对吧因为你可以解释他这个你可以迎来解释就是他这个他可能就是这个写是在这儿吗然后他读在这儿嘛所以他可以满足Linear Beta正是因为这个rate等于4发生了,所以它就戳破了这个它不满足linearability的这个事情这个真相是吧 否则的话你可能还懵在鼓励你可能还是觉得满足那点非得见所以理论上来说,你从理论分析的角度,说这个database满足linearability,是吧?像你刚才举的例子是理论上不满足linearability但从实际观察的角度是满足利点赔的如果Client B最后的那个read,只要有一部分跟Client A read等于4有一点点重合,它也满足了你的ability [90:00] 对,你从观察的角度来讲,你只要有一个解释能解释它满足LinearPilitude,就是满足LinearPilitude。好的除非你能从理论证明它不满足Linearability嗯我觉得我自己读这张的时候,当然我现在读一下可能相对比较轻松一点,但我之前读的时候还是挺烧闹的好 如果没有问题就这样的 今天也是最后一张讲这个Theory了 我觉得还是比较有趣的,如果大家有兴趣的话以后可以就是比如说有一个读书的一个什么一个meeting是吧,我们可以教论一下读书心得啊,这样的话相对来说我比较轻松一点,我们就是可以一张一张的读,然后讨论一下读书的心得,没必要我去准备一个slides,我觉得这样子用的我是相对来说比较可以接受的,但是准备slides这个工作量确实太大了一点,我还得再重新读一遍这一张。然后把其中比较难的一部分给摘出去,然后把简单的那部分说下来,但是其实简单一部分有时候也很难,有时候自己也把自己绕运了,也是挺正常的但是,如果有读书的话,我可以一周读一脚脏啊这样的,我觉得还是比较sustainable的。这个现在来说对我个人不是很sustainable。今天就到这好了谢谢大家谢谢大家谢谢大家。