前两天有个做后端的朋友跟我吐槽,说他们在做大版本升级,数据库要从 MongoDB 的老版本迁移到新集群,结果折腾了整整一个周末,数据还在同步,业务却断断续续报错。我问他用了什么工具,他说直接用了 mongodump 和 mongorestore。我说兄弟,这俩工具看着简单,但真要跑几十个 TB 的数据,坑比你想象的多。其实 MongoDB 迁移这事儿,说穿了就是个系统工程,不是单纯把数据从 A 点搬到 B 点。你得考虑业务能不能停、数据量有多大、有没有索引、分片、副本集这些结构,甚至还要算清楚网络带宽和磁盘 I/O 的压力。

很多人一上来就想着用 mongodump 导出成 BSON 文件,然后再 mongorestore 导回去。这个方案对小数据量确实管用,比如几十个 GB,跑个几小时就能完事。但一旦数据上了 TB,或者有大量的小文档,问题就来了。mongodump 默认是单线程的,它会把每个集合的文档一条一条读出来,写入 BSON 文件。这个过程不仅慢,还会占用源库的 I/O 和 CPU 资源,如果在业务高峰期跑,很容易拖慢正常查询。更糟的是,如果你有分片集群,mongodump 不会自动处理分片的元数据,导出的数据可能分布不对,恢复后还得手动重新分片。我见过一个案例,有人用 mongodump 导出了 10 TB 的数据,结果发现导出的 BSON 文件里包含了大量已删除的文档,因为存储引擎并不会立即回收空间,那些过期文档仍在磁盘上。最终导出的文件比实际数据大了约 30%,恢复时间翻了一倍。
如果你对业务中断时间有容忍度,比如允许停机几小时,mongodump + mongorestore 组合仍可行,但必须做优化。关键点在于:先备份索引策略,因为 mongorestore 默认会重建索引,而索引重建非常消耗资源。建议使用 参数跳过索引,等数据全部恢复完成后再手动创建索引。另外,可以用 参数增加并发数,例如设为 4 或 8,让多个集合同时导出。但并发数太高会压垮源库,需要根据 CPU 和磁盘负载来调节。还有一个容易忽略的细节:mongodump 导出的 BSON 文件默认不包含 oplog,这意味着无法实现增量迁移。如果业务不能长时间中断,这个方案基本就不可行。
对于不能停机的场景,MongoDB 官方推荐的是副本集迁移法。思路很简单:在目标集群上搭建一个副本集,然后在源集群的配置里把目标集群的节点作为从节点加入进来。等数据同步完成后,再切换主节点,让目标集群接管业务。这个过程的精髓在于利用 MongoDB 原生的复制机制,数据同步是实时的,业务几乎无感知。但实现起来有几个硬门槛:源库和目标库的网络必须互通,延迟要低,带宽要足够。跨机房甚至跨地域时,同步延迟会很高,网络抖动可能导致同步中断。另外,源库的 oplog 必须足够大,因为从节点在追赶主节点时需要读取 oplog 中的操作记录。如果 oplog 太小,追赶过程中主节点已经覆盖了旧记录,从节点就会报错,只能重新全量同步。因此迁移前一定要检查 oplog 的大小,通常建议保留至少 24 小时的操作记录。
还有一种常见场景是迁移到 MongoDB Atlas 这种云托管服务。很多人以为 Atlas 有图形界面,点几下就能搞定,其实没那么简单。Atlas 提供的迁移工具叫 Live Migrate,本质上也是通过复制机制实现的,但需要在源库上开启认证和 SSL,并且要开放特定端口。如果你用的是自建集群,防火墙规则、VPC 对等连接、白名单配置每一项都可能成为卡点。我帮人处理过一个案例,源库在阿里云,目标库在 AWS 的 Atlas,因为两个云厂商的网络策略不同,折腾了两天才打通。更麻烦的是,Live Migrate 在迁移过程中会持续监控延迟,如果延迟超过阈值,它会自动暂停迁移,等你调整网络后再恢复。这时候如果业务流量很大,暂停后重新追赶数据又需要时间,整个迁移周期就会被拉长。
如果对数据一致性要求极高,比如金融或审计场景,上面这些方案都不够严谨。这时可以考虑 mongomirror 或第三方工具如 PeerDB。mongomirror 是 MongoDB 官方出的工具,能从源库的 oplog 实时读取变更并应用到目标库。它最大的优势是可以保证最终一致性,并且支持断点续传。但配置比较复杂,需要指定 oplog 的起始时间戳,还要确保源库和目标库的版本兼容。我见过有人用 mongomirror 迁移了三个月的数据,结果因为版本差异,某些聚合管道的语法不兼容,导致部分文档的更新丢失。所以迁移前一定要做兼容性测试,尤其是从 3.x 迁移到 5.x 时,很多旧语法已废弃,必须提前改代码。
说说迁移后的验证和收尾工作。很多人迁移完就以为万事大吉,结果第二天业务报错才发现索引没建、权限没配、监控没接。正确的做法是,在切换流量之前先做一次完整的全量校验。可以写脚本对比源库和目标库的文档数量,或者用 做抽样检查。更严谨的做法是,用 mongodump 导出源库的元数据,包括索引、分片规则、用户权限,然后在目标库上逐项重建。还有一个容易被忽视的点:迁移后要修改应用的连接字符串。如果你的应用是微服务架构,有几十个服务节点,改连接字符串会很麻烦。建议提前把连接信息放到配置中心,或者用 DNS 做动态解析,这样切换时只需要改一处配置。
说一千道一万,MongoDB 迁移这事没有银弹。你得根据业务场景、数据量、停机容忍度、网络条件综合选择方案。小数据量用 mongodump,大数据量用副本集复制,跨云用 Live Migrate,高一致性用 mongomirror。但无论选哪个,都要提前做测试,并准备好回滚方案。我见过太多人拍脑袋选方案,结果迁移到一半发现走不通,只能回滚重来。记住一条铁律:任何没经过压力测试的迁移方案,都是定时炸弹。


