摘要
从一个 MongoDB 集群迁移到多模型架构时,难点不只是把集合复制过去,而是确认索引、写入顺序、读一致性和回滚条件。本文参考榜单中的 MongoDB 迁移主题,整理一份不绑定厂商的迁移评审方法:先建立字段与索引清单,再设计双写和回放窗口,最后用可量化的差异阈值决定切换。示例不代表连接过真实生产集群。
先盘点事实,不先写迁移脚本
迁移输入应包含集合规模、文档大小分布、热点键、TTL、唯一索引和变更流使用情况。不要只统计文档数量;数组嵌套、稀疏字段和历史脏数据都会改变目标端的存储与查询行为。为每个集合建立字段类型矩阵,标出源端允许而目标端不允许的组合,并为异常文档定义隔离队列。
索引清单需要与查询清单关联。对每条关键查询保存过滤字段、排序字段、返回字段和期望延迟,迁移后用同一批参数回放。目标端即使支持同名索引,也可能使用不同的排序和空值规则,不能把索引创建成功当成查询等价。
双写必须可观测、可停止
双写期间由一个明确的写入 ID 贯穿源端、目标端和变更日志。先写主端还是先写目标端要根据业务容忍度决定,但必须记录每次写入的序号和结果。目标端失败时,补偿队列保存原始事件和重试次数;补偿无法完成时进入人工处理,不应静默丢弃。
读流量可以按租户或用户分批切换。每批切换前先比较同一文档在两端的哈希、关键字段和版本号,比较结果只用于判断差异,不直接覆盖目标数据。发现差异时标注来源:延迟、类型转换、业务计算还是历史脏数据。只有能解释的差异才允许进入下一批。
用回放样本验证行为
回放样本应覆盖新增、更新、删除、重复事件和乱序事件。对每类事件记录源端最终状态、目标端最终状态以及中间重试次数。更新操作若不是幂等的,必须改成带版本条件的更新;删除操作则要明确是软删还是物理删,避免恢复时缺少墓碑记录。
一致性不能只看最终数量。还要检查关键查询的结果集合、分页边界、聚合结果和 TTL 到期行为。对高峰流量可使用脱敏后的事件比例回放,观察写入延迟、锁等待和磁盘增长。任何超过预算的指标都应触发暂停,而不是通过提高并发掩盖问题。
切换与回滚条件
切换前给出一张短清单:双写队列为空、关键集合差异低于阈值、索引已预热、监控和告警已开启、值班人确认回滚命令。切换后先只读验证,再逐步开放写入。回滚窗口内保留源端写入能力,但禁止两端同时接受无序写入。
回滚不是把流量开关拨回去那么简单。需要确定最后一个已确认版本、未同步事件和目标端产生的副作用。若业务包含外部通知或计费,应把这些副作用拆成可补偿步骤,并在回滚记录中逐项确认。迁移完成后再清理旧链路,至少保留一段可审计时间。
容量评估也要放进切换门槛。目标端的磁盘增长不仅来自文档,还包括索引、预写日志、临时文件和压缩差异。用峰值写入速率乘以最长补偿窗口估算缓冲区,并为重建索引预留额外空间。监控磁盘水位、复制延迟、队列年龄和慢查询数量,任一指标达到红线就暂停扩批。
数据校验可以采用分层抽样。先按集合、时间段和热点键分层,再对每层抽取固定比例,比较字段哈希和业务计算结果。发现差异时保存原文档 ID、两端版本和转换日志,不要只保存一个总数。对金额、状态和权限等关键字段使用全量校验;对大文本字段可使用分块哈希,减少网络传输。
应用层也要准备兼容窗口。读代码先接受两种字段形状,写代码在双写稳定后才启用目标端特有字段。接口返回中增加数据来源和版本,出现异常时可以快速按版本回放。切换结束后删除兼容分支前,先确认所有消费者已经升级,并保留一份删除前的依赖清单。
迁移复盘不应只记录成功耗时。把每次暂停、补偿、差异分类和人工决策写入账本,下一次迁移可直接复用阈值和样本。若某类差异连续出现,应回到字段模型或业务事件设计,而不是把它永久加入例外名单。
安全与合规检查也不能被数据正确性替代。迁移账号只授予所需集合和操作权限,凭证在窗口结束后立即撤销。传输链路启用加密,校验文件和临时导出设定保留时间。脱敏样本仍要避免包含可重新识别的组合字段,测试完成后按清单清理,并保存清理结果。
正式切换当天建立统一时间线,记录每个开关、指标截图、批准人和异常。命令由一人执行、另一人复核,避免值班压力下跳过前置条件。若达到暂停阈值,先阻断新批次,再处理在途事件;恢复前重新比较差异和容量,而不是从上次百分比直接继续。
切换完成后仍需观察完整业务周期,覆盖定时任务、月末批处理和长尾查询。观察期结束的判断应由指标和差异报告决定,而不是只看当天没有告警。
旧集群退役前再次核对备份可恢复性、审计保留期和访问账号清单。
结语
多模型迁移的质量取决于差异是否可解释。通过字段矩阵、查询回放、版本化事件和明确的暂停条件,可以把一次高风险切换拆成若干小窗口。迁移方案评审时,最值得追问的不是"能不能复制",而是"出现差异时能否定位、停止并恢复"。