故障切换后数据回补怎么做?
简化版
切换后回补要先冻结旧主写权并确定权威时间线,再根据日志位点、版本或业务流水找出缺口,以幂等方式分批补写、校验并留审计。 不能把旧站全量覆盖到新主;切换窗口可能同时包含缺失写、重复写和冲突写,必须分类处理。
详细版
记录切换 epoch、旧主最后确认位点、新主接管位点和客户端成功凭证。单主日志可从共同水位增量追赶;双边可能写入时,要按业务主键、版本向量或账务流水识别冲突,资金类不能用简单最后写胜出。
回补任务带唯一键和 expectedVersion,按租户/分片限速,失败可重试。完成后用条数、金额、checksum 与业务不变量多层对账,再逐步解除只读或回切。原始差异和人工决策要保留,便于审计和再次执行。
完整版教学
一、先明确回补面对的三类差异
故障窗口内可能出现旧主有、新主没有的缺失记录;两边都有的重复动作;以及同一业务对象被两边不同修改的冲突。三类问题不能都用“把旧库同步过去”解决,否则可能覆盖切换后合法的新数据。
记忆钩子:回补先选历史,再补缺口;“来源可读”不等于“来源权威”。
二、fencing 与权威时间线
切换时生成更高 epoch,并让存储、网关或租约拒绝旧 epoch 写。只有确认旧主失去写权后,才能定义新主接管点。若旧主在网络分区中继续成功响应,系统已经产生双历史,必须进入冲突协调而非普通日志追赶。
epoch 41: old primary, last durable LSN=8000
epoch 42: new primary starts at LSN=7990
gap candidate: 7991..8000(仍需确认哪些已对客户端成功)
三、建立可审计的差异清单
| 差异 | 证据 | 处理 |
|---|---|---|
| 新主缺失 | commit log/外部流水 | 幂等补写 |
| 两边重复 | 业务唯一键 | 去重并复用结果 |
| 并发冲突 | 版本/时间线 | 业务合并或人工裁决 |
| 字节损坏 | checksum | 从可信副本修复 |
先把差异固化为带来源、版本、原因和状态的任务表,避免扫描结果变化后无法复盘。
四、回补必须条件写和幂等
任务以 bizId + operation 做唯一键,写入时校验目标 expectedVersion。若目标已经有更高版本,任务进入冲突队列而不是覆盖。任务状态可为 PENDING、APPLIED、CONFLICT、FAILED,重复执行 APPLIED 任务直接返回原结果。
UPDATE target SET value=?, version=42
WHERE id=? AND version=41
影响行数为 0 表示目标已变化,需要重读判断,不能当作成功。
五、限速与优先级
回补会争用数据库 IOPS、日志和网络。若差异 120 万条、每批 500 条、每秒 10 批,理论至少 240 秒;实际还要留重试与校验时间。先补资金、库存等核心数据,再补统计和衍生索引,并根据前台 P99 动态降速。
大批更新还可能产生复制 lag 和缓存失效风暴。按分片错峰、限制事务大小,并让下游 CDC 能识别 source=backfill,防止重复触发外部副作用。
六、多层对账和恢复出口
条数相等不代表金额正确,checksum 相等也可能基于错误快照。校验至少包括主键集合、版本/哈希、金额汇总、状态机不变量和外部支付流水。随机抽样用于发现格式问题,核心账务则要全量对账。
监控待补数、最老差异年龄、处理速率、冲突率、失败重试和业务对账差额。只有差异收敛、复制恢复、缓存预热且核心不变量通过,才逐步退出只读或开始 Failback。
七、常见误区与追问
- 误区:旧主恢复后全量覆盖新主最快。 会删除或覆盖切换后的合法写入。
- 误区:按更新时间最新者获胜即可。 时钟可能漂移,资金冲突也不能 LWW。
- 误区:回补脚本成功退出就代表完成。 还需多层对账与差异归零。
- 误区:回补流量属于后台,可以不限速。 它会争抢前台数据库和复制资源。
- 追问:客户端超时但旧主已提交怎么办? 用请求 ID、提交日志和外部凭证确认,幂等补写或返回原结果。
- 追问:两边都修改同一订单怎么办? 根据状态机合法迁移做业务裁决,无法自动判断则人工审核。
- 追问:如何防回补再次触发通知? 下游消费幂等,并区分回补事件与首次业务事件。
八、加强记忆
切换后回补按“封旧写—定时间线—列差异—条件补写—限速—多层对账”执行。缺失、重复、冲突分别处理,所有任务可重试且可审计。恢复不是把两边数据变得看起来相同,而是证明权威业务状态重新一致。