← 返回题目列表

分布式存储如何做数据修复?

高频 困难 第 16 / 27 题 更新于 2026/10/04
数据修复Read RepairAnti-EntropyMerkle Tree
学习 AI 实战项目

简化版

分布式存储修复不是简单地“从多数副本拷一份”。系统应先区分副本落后、数据损坏、并发版本、缺副本和错误放置,再依据共识提交记录、对象版本、checksum 或业务规则选择可信来源。修复过程采用临时副本或条件写,完成全量复制、增量追赶和校验后才恢复服务资格,同时限制带宽并保留审计与回滚证据。

详细版

副本落后可按日志位点追赶,差距过大时安装快照;checksum 失败的块要先隔离,再从版本正确且校验通过的副本重建;无主多写产生的并发版本不能当成损坏覆盖,而要按因果关系和业务规则合并。

修复任务应有明确状态机,例如 DETECTED -> QUARANTINED -> COPYING -> CATCHING_UP -> VERIFYING -> ACTIVE。复制期间记录基准水位并追增量,目标端通过 epoch、日志 index 或 CAS 防止旧修复覆盖新写。只有 checksum、版本水位、副本拓扑和必要业务不变量全部通过,目标副本才能重新参与读取或仲裁。

调度器按剩余故障容忍度、数据不可读风险、损坏范围和墓碑安全窗口排序,并限制源节点、目标节点、机架链路与集群总并发。监控最老未修复时间、降副本时长、复制与重试字节、校验失败、追赶 ETA 和复验通过率。

完整版教学

一、先判断修复对象出了什么问题

“副本不同”不是单一故障。落后副本只是缺少已提交后缀;静默损坏是已有字节未通过 checksum;两个并发版本可能都合法;节点永久丢失需要补建新副本;副本落在错误故障域则属于拓扑修复。分类错误会把正常并发当坏数据删除,或把损坏字节继续扩散。

故障类型主要证据典型动作
日志落后term/index、commit 水位日志追赶或安装快照
块损坏checksum、对象版本隔离后从健康来源重建
并发版本版本向量、业务状态合并、保留 siblings 或人工处理
副本丢失成员配置、放置记录在合格节点补建副本
放置违规故障域和策略版本新建合格副本后移除旧副本

二、真值来源必须有证据

共识复制可以依据已提交日志、Leader 的匹配前缀和快照元数据确定合法历史。对象存储通常核对对象 ID、generation、长度、etag/checksum 和不可变清单。无主多写系统则要判断版本支配关系;互不支配的版本是冲突,不应由修复器擅自选一个覆盖。

三个副本中两个内容相同也不必然代表正确:它们可能共同落后,或被同一软件错误污染。修复源至少要同时满足版本正确、完整性校验通过和当前拓扑授权,必要时再与备份、审计流水或业务不变量交叉验证。

记忆钩子:副本数量提供线索,提交与版本证据才决定谁有资格成为修复源。

三、把修复做成可恢复的状态机

检测到异常后先把坏副本标记为 SUSPECT 或 QUARANTINED,阻止它继续服务强一致读取或充当复制源。控制器创建带 repairId、对象范围、源版本和目标节点的幂等任务;执行器重启后根据持久化状态续跑,而不是重新猜测修复方向。

DETECTED -> QUARANTINED -> SOURCE_SELECTED
         -> COPYING -> CATCHING_UP -> VERIFYING
         -> ACTIVE | FAILED

状态转换使用条件更新,避免两个控制器同时修同一范围。失败任务保留原因、已复制水位和临时文件,确认无人引用后才能回收。

四、在线修复如何不丢并发写

修复持续数分钟或数小时,源数据仍可能变化。执行器先记录基准快照或日志位置,复制稳定前缀,再持续追赶该位置之后的增量。目标追到切换水位后短暂建立屏障或通过协议确认无缺口,才能加入当前副本集合。

块或文件修复采用 copy-on-write:写入临时位置,校验长度、checksum 和索引,fsync 后原子替换。单键修复使用预期版本 CAS;若目标在修复期间已收到更新版本,旧 repair 必须失败并重新判断,不能覆盖新值。

五、不同规模选择不同修复通道

少量读到的旧键可触发 Read Repair;后台 Anti-Entropy 负责发现冷数据差异;共识副本优先按日志追赶,日志已截断时改用快照;整盘丢失通常直接重建副本;纠删码对象则读取足够的数据块和校验块重构缺块。

这些机制负责“如何发现或搬运”,不负责自动决定真值。Merkle Tree 只能定位不一致范围,checksum 只能证明字节与记录值是否匹配,快照也必须带可信水位。控制器仍要根据故障类型选择正确通道。

六、修复期间仍要守住副本安全

补建新副本时,旧副本不能在新副本验证完成前被计入可删除数量。调度器还要检查目标主机、机架、可用区、容量水位和当前恢复负载,避免为了补数量把副本都放进同一故障域。

修复会争抢源端读取、目标端写入、网络、CPU 和 Compaction 预算。仍有 quorum 时,可按“接近失去 quorum、低于目标副本数、检测到损坏、普通均衡”分级,并设置每节点和集群总限速;已经失去 quorum 的共识组不能靠普通成员变更自行恢复,必须进入受控灾难恢复并重新证明权威历史。加速也不能把仍存活的源节点压垮,否则一次局部故障会演化成级联故障。

墓碑也是合法版本。旧副本尚未完成覆盖修复前不能过早回收墓碑,否则恢复节点可能把已删除值重新带回;超过允许离线窗口的节点应完整重建,不能直接重新入组。

七、复验通过后才能恢复资格

RPC 返回成功只说明数据传输结束。系统还要在共同水位核对对象数、版本范围、checksum 或 Merkle 根,确认增量没有缺口,并验证副本数与故障域约束。高风险数据可再运行状态机不变量或业务对账。

目标副本通过复验后,控制面以新配置版本把它标为 ACTIVE;观察期结束后才清理旧副本和临时数据。若复验失败,应回到隔离状态并保留证据,不能边报错边继续对外提供数据。

监控至少包括 under_replicated、oldest_repair_age、待修复字节、有效吞吐、追赶 lag、checksum 失败、CAS 冲突、复验失败率、降副本时长和修复对前台 P99 的影响。

八、常见误区与追问

  • 误区:从多数副本复制一定正确。 多数可能共同落后或共同损坏,必须核对提交、版本和校验依据。
  • 误区:复制完成就可以立即上线。 还要追增量、复验完整性并更新成员资格。
  • 误区:修复任务是后台流量,可以不限速。 它会同时消耗健康源节点和目标节点资源。
  • 误区:并发版本属于坏数据。 它可能是协议允许的合法写冲突,需要业务合并而非覆盖。
  • 误区:失去 quorum 后自动补一个副本即可恢复。 正常成员变更也需要 quorum,此时必须走受控灾难恢复并确认权威历史。
  • 追问:日志追不上怎么办? 安装带可信水位的快照,再追快照后的日志。
  • 追问:如何防止旧修复覆盖新写? 使用日志水位、epoch 或预期版本 CAS。
  • 追问:何时算修复完成? 数据、增量水位、完整性和副本拓扑全部复验通过之后。

九、加强记忆

完整修复链路是:先分类故障,再用提交、版本和校验证据选择来源;随后隔离异常副本,以快照或条件写复制并追赶增量;最后复验数据与拓扑,通过后才恢复服务资格。Read Repair、Anti-Entropy、日志追赶和快照只是不同通道,安全性来自可证明的真值、受控状态机和上线前复验。