第 12 章 —— 基于摘要的差异检测与副本修复
本章目标: 本章完成后,开发者能够用 digest 发现差异,解释 replay 与 snapshot 的选择条件,并拒绝会让请求方倒退的 repair。
学习目标
- 解释 digest、anti-entropy 与 repair 的关系。
- 根据保留窗口和估算成本选择 replay 或 snapshot。
- 识别「请求方比来源更新」和「同序列但更完整」的倒退风险。
- 区分当前状态修复与业务事件历史重放。
前置条件
- 已完成第 11 章的 delta 路径。
- 理解在线消息可以丢失,但集合最终需要重新收敛。
- 理解 repair 是后台修复过程,不属于本地写入事务。
案例进度
node-b 离线期间错过了 10 条 route hint
更新。恢复后,它没有要求 node-a
重发「所有业务事件」,而是先报告自己的 collection digest,由 source
判断从保留 delta 继续还是传输当前 snapshot。
从差异到修复计划
digest 是状态摘要:它让双方判断 observed sequence、entry 数量或分桶 hash 是否存在差异。它不需要携带完整值,也不保证自己就是权威;它只是下一步协商的输入。
AdaptiveRepairPlanner 的决策边界可以压缩成四条:
- 没有差异时返回
NONE。 - 请求方进度领先,或同 sequence 下内容更完整时,不向它发送较旧 snapshot。
- 请求方进度仍在 source 的 replay 保留窗口内时,比较 replay 与 snapshot 的估算成本。
- replay 已不可用时,使用 snapshot 补齐当前状态。
Replay 与 Snapshot 不只是大小差异
| 维度 | Replay | Snapshot |
|---|---|---|
| 内容 | 从指定 sequence 开始的保留 delta | 当前集合状态分块 |
| 适用 | 缺口连续且仍在保留窗口内 | 缺口过旧、过大或 snapshot 更便宜 |
| 优点 | 增量小,保留演进顺序 | 不依赖完整增量历史 |
| 风险 | 日志窗口不足;大量小消息 | 大传输;接收端需安全组装和切换 |
| 不是 | 业务事件审计重放 | 数据库备份或跨资源事务恢复 |
自适应选择依赖 peer profile 的延迟、吞吐和历史样本。没有 profile 时,planner 回退到固定策略;这比用一次偶发慢请求立即改策略更可预测。
绝不能修复成更旧
repair 失败会留下显式差异;更隐蔽的风险是 repair 返回“成功”却把请求方覆盖成旧状态。例如,请求方 sequence 为 101,而 source 只有 100。此时即使 hash 不同,也不能把 source snapshot 当作权威状态倒灌。
同样,在 sequence 相同的情况下,请求方拥有更多 entry 时,source
不应把较少 entry 的 snapshot
发过去。AdaptiveRepairPlannerTest 把这两种情况都固定为
RepairMode.NONE。
Anti-entropy 是持续控制环
一次在线 delta 漏失后,系统需要周期性 sweep:
交换摘要 → 判断差异 → 生成 repair plan → 传输 → 应用 → 再比较
控制面消息也可能丢。ChaosIntegrationTest 注入 50%
控制面丢失,验证后续 sweep 仍能发现并修复。一次 repair
请求成功只能说明单次操作完成;修复过程还需通过最终摘要一致来确认。
反例与故障注入
- 将 requester sequence 设置为 source 之前,观察 planner 拒绝倒退。
- 将 requester 放到 replay 窗口之外,观察计划切换为 snapshot。
- 使用 profile 让 snapshot 估算更快,观察即使 replay 可用也选择 snapshot。
- 丢掉第一轮控制面消息,观察后续 anti-entropy sweep 补偿。
实验
cd submodule/dsm
mvn -q -pl dsm-sync,dsm-integration-test -am \
-Dtest=AdaptiveRepairPlannerTest,ChaosIntegrationTest \
-Dsurefire.failIfNoSpecifiedTests=false test在 repair-scenarios.json 中,为每个 requester/source
组合选择 NONE、REPLAY 或
SNAPSHOT,并写出拒绝倒退的理由。
实验验收卡
| 字段 | 内容 |
|---|---|
| 运行命令 | 上述 Maven
聚焦测试;node --test tests/chapter-assets.test.mjs |
| 输入或故障 | replay 窗口内/外、成本样本、请求方领先、控制面丢失 |
| 可观察结果 | planner 选择可解释;请求方不倒退;后续 sweep 最终修复 |
| 证据等级 | E2 planner 行为 + E3 chaos repair |
| 本实验未证明 | 生产数据规模下的最佳阈值、跨区域带宽成本、业务历史完整性 |
回顾
- digest 发现差异,repair plan 决定如何补齐。
- replay 可用不代表一定更便宜,snapshot 也不天然更权威。
- 请求方领先或更完整时需要拒绝倒退。
- anti-entropy 是重复控制环,当前状态收敛不等于业务事件重放。
下一步
第 13 章把注意力转向观察者:即使集合能收敛,慢订阅者也可能让本地变更缓冲溢出。