状态机复制、Raft 与多数派
状态机复制需要共同认定的决策顺序,不只是多份“最新字节”。
拆掉一个三节点集群
暂停投票节点、替换 Leader,再尝试提交。
正在加载互动… 交互需要 JavaScript;正文仍可直接阅读。
学习目标
解释日志复制、选举与 Quorum 相交,预测三投票节点的行为,检查真实崩溃与暂停记录。
前置:一致性约定和本地持久化文件。
原理:同一个顺序,确定性地执行
副本从相同状态出发,认定同一份有序命令日志,再确定性执行命令。对顺序达成一致,才让状态相同。时间、随机数、外部调用等不确定因素必须在设计中被消除或显式记录。
Raft 把选主、日志复制和安全规则分开。Term 标识选举时期;每个投票者在每个 Term 最多投一票,候选者的日志还必须足够新。Leader 复制日志,并依协议的当前 Term 规则推进提交。尤其跨 Term 时,“某条记录在两块盘上”不是完整的 Raft 提交定义。
客户端
│
leader n1
╱ ╲
voter n2 voter n3
N = 3,多数派 = 2。任意两个多数派必然相交。
相交 + 投票/日志规则,保护已提交决策。相交保证两项相互冲突的决策不能由完全分离的多数派分别证明;日志与投票规则让这个交点发挥作用。三个投票者中两个可达时,在有利调度下可以选举并提交;只剩一个就无法组成多数派。选举超时帮助系统推进,不证明旧 Leader 已经物理死亡。
共识与原子提交解决不同问题
Raft 为一个复制组决定日志顺序。两阶段提交协调多个事务参与者是否共同提交。2PC 中已准备的参与者可能等待协调者决策;用复制服务提高协调者决策的持久性,也不意味着两个协议可以互换。本实验只有一个 etcd 共识组,不实现跨分片事务或 2PC。
真实实验 A:先失去 Leader,再失去多数派
- 写入一个收到成功确认的值,用维护状态接口确定 Leader。
- 仅对这个自己创建的进程发送 SIGKILL。等待其他 Leader,读取旧值,再完成一笔新写。
- 用原来的数据目录重启该节点,检查它能读到两次写。
- 用 SIGSTOP 暂停一个 Follower,向可达节点写入;剩下两个投票者仍可推进。
- 恢复后再暂停两个 Follower,等待 1.4 秒,以 700 ms 截止时间发起写与默认线性一致读。记录未知结果,恢复节点后核对那笔写。
安装后执行 python3 scripts/run_all.py --repeats 3。首版每次重复都会执行三个实验家族。查看全部保存结果,包括超时写在恢复后的值。“700 ms 内未获成功”才是测量事实,不是普遍的延迟上界。
范围:同一主机上的真实 etcd 进程,各有独立 WAL 目录。暂停使投票者不响应;它不是非对称网络丢包实验,不是磁盘丢失测试,也不能证明多机性能。
自测
为什么不让唯一可达节点选出新 Leader?
它拿不到多数票。让每个隔离部分都能决策,会破坏相交论证,允许不兼容的决定。
实验能证明任何已提交写永远不丢吗?
不能,它只检查特定故障下的指定已确认值。普遍的安全保证来自协议与实现假设;运行提供有限范围的实现证据。
原始资料
- Ongaro 与 Ousterhout:Raft 扩展论文,重点 §§2、5、8。
- etcd FAQ:提交与运行。
- etcd 故障模式:多数派丢失与选主。
对照 MIT 6.5840 学习
Lecture 6: Fault Tolerance: Raft (1) · Lecture 7: Fault Tolerance: Raft (2) · Lab 3: Raft
运行真实三投票节点连接分区,对照多数派分区与三个孤立节点。
python3 scripts/run_network.py --repeats 3 --out build/my-network.json本 Lab 可运行练习为独立原创,不是所链接 MIT 作业的解答。安装方法见复现页;不代表注册、评分或认证。
检索已核验课程地图 →