恢复是一次带有义务的状态变更:保留已知决策,核对未知结果,使失效假设不再被沿用。

学习目标

区分重启、追赶与灾难还原,建立证据链,写明尚未测试的内容。

前置:复制、未知结果与所有权代次。

三条恢复路径

重启重新打开相同持久化文件,通过 WAL 与已保存元数据恢复节点本地决策。追赶让落后节点利用当前已提交日志或快照补齐状态。灾难还原在旧多数派无法返回时,从备份重建逻辑集群。三者的身份、数据丢失窗口和客户端影响不同。

崩溃 + 原文件 → 重启 → 追赶 → 读取已确认值
落后节点      → 日志/快照传输 → 核对当前状态
多数派永久丢失 → 备份还原 → 新集群 + 客户端/epoch 方案
                                      ↑ 本版未执行

实验 A 在数据目录完好的条件下执行前两条路径。它不执行快照备份还原、不验证恢复点目标,也不保证整台主机毁坏后可恢复。复制数据库文件可能遗漏只在 WAL 中的数据;备份流程与完整性检查应属于单独执行的还原方案。

未知写需要核对

两个投票者暂停时,客户端超时;恢复后,运行器读取尝试写入的键,记录它是否存在。两种结果都可能符合此前的客户端不确定性。业务关心结果时,应有操作身份或可查询的结果,不能从传输截止时间推断“失败”,也不能盲目重放非幂等意图。

恢复还会影响辅助状态。还原后的协调者 revision 可能低于下游 fencing 记录;Watch 消费者可能保留过时缓存;去重记录可能比外部系统中的效果更旧。因此要一起考虑 epoch、缓存失效与效果/结果核对;只恢复键值字节并不是完整的应用协议。

先证据,后解释

  1. 注入前记录实现版本与拓扑。
  2. 把调用者观测与服务端提交证据分开。
  3. 写明不变量及检查它的具体断言。
  4. 保留每次重复,包括异常,不用成功故事覆盖失败运行。
  5. 对导出文件计算哈希;原始运行材料留本地,仅发布审计后的合成字段。

证据页展示提交基线中的全部重复。results/index.json 保存机器可读报告的哈希。耗时是依赖本机调度的描述值;三次重复用于核查机制,不代表置信区间或服务等级目标。运行器断言失败会终止,不会生成新的通过报告。

动手:写一份有边界的事件记录

使用保存的多数派丢失记录,写四句话:客户端观察;故障前已确认的值;恢复后的核对结果;剩余不确定性。再把一个假设改成“旧节点磁盘永久毁坏”,说明哪些已执行检查仍适用,哪些必须另做还原实验。

观察:调用者在截止时间内没有收到成功响应。
已知决策:恢复后读到了故障前已确认的值。
核对:查看 unknown_write_after_recovery,不靠猜测。
范围:这次没有毁坏存储,也没有做数据包分区。

下一步可增加备份,只删除自己的一次性集群数据,在新的独占目录还原,再检查内容与客户端 epoch。首版将它列为设计练习,不冒充已执行结果。

自测

为什么超时写的最终值有变化也要保留?

差异反映未知结果与调度,是有意义的证据。隐藏差异会教出“超时等于回滚”的错误关系。

哈希能证明测量真实可靠吗?

不能,它只能帮助发现某份导出文件被更改。复现、源码检查与明确测量方法是另外的要求。

原始资料与后续路线

接着可读 MySQL Lab 的事务与本地锁证据、Streaming Lab 的端到端状态/效果边界、Distributed Compute Lab 的重算与重试,以及 Java Runtime Lab 的中断和调用者取消。它们处于不同层次,都不自动提供本章的分布式保证。