一、MongoDB备份为什么让人头疼

作为NoSQL数据库的扛把子,MongoDB用起来是真香,但说到备份恢复这事儿,不少运维同学都要挠头。原因很简单——它和传统关系型数据库的备份逻辑完全不同。

举个典型场景:你用了分片集群,突然某个分片的主节点挂了。这时候如果用传统的mongodump,可能会遇到以下问题:

  1. 备份期间数据库持续写入,导致备份数据不一致
  2. 恢复时分片配置信息丢失
  3. 大数据量备份慢到怀疑人生
// MongoDB技术栈示例:基本备份命令
mongodump --host=localhost --port=27017 --db=production_db
// 问题1:没有指定--oplog会导致备份期间新增数据丢失
// 问题2:分片集群需要额外处理config server

二、实战派解决方案

方案1:官方推荐的组合拳

MongoDB官方其实给出了黄金组合:副本集 + Oplog。这就像给数据库上了"时光机",可以回滚到任意时间点。

// 创建全量备份
mongodump --host=rs0/localhost:27017,localhost:27018 --db=orders --out=/backup/full

// 增量备份通过oplog实现
mongodump --host=rs0/localhost:27017 --collection=oplog.rs --db=local --query='{ts:{$gte: Timestamp(1630000000,1)}}' --out=/backup/incr

方案2:文件系统快照大法

对于超大型数据库,可以配合LVM或AWS EBS做快照:

# Linux技术栈示例
lvcreate --size 1G --snapshot --name mongo_snap /dev/vg_mongo/mongo_data
# 注意:需要先执行fsync锁住数据库

三、恢复时的骚操作

恢复数据最怕什么?当然是恢复完发现数据对不上!这里分享几个救命技巧:

  1. 预演恢复:先在临时环境测试
  2. 索引优先:先恢复索引再恢复数据
  3. 流量控制:恢复期间限制应用连接
// 带索引恢复的示例
mongorestore --host=rs0/newserver:27017 --db=orders --noIndexRestore /backup/full/orders
mongorestore --host=rs0/newserver:27017 --db=orders --noCollectionData /backup/full/orders

四、避坑指南

  1. 分片集群:config server必须第一个恢复
  2. 版本兼容:3.6的备份不能直接恢复到4.0
  3. 内存陷阱:恢复前调大cacheSizeGB
// 分片集群恢复顺序
1. 恢复config server
2. 恢复shard1
3. 恢复shard2
// 注意每个步骤间隔不要超过oplog窗口

五、进阶技巧

对于特别重要的生产环境,可以考虑这些方案:

  • 延迟副本集:专门用于数据恢复
  • 混合云备份:本地快照+云存储
  • 校验脚本:自动比对数据一致性
# Python技术栈的校验脚本示例
from pymongo import MongoClient

def verify_restore(src_uri, dst_uri):
    src = MongoClient(src_uri)['mydb']
    dst = MongoClient(dst_uri)['mydb']
    for col in src.list_collection_names():
        assert src[col].count_documents({}) == dst[col].count_documents({})

六、总结与选型建议

  1. 中小规模:副本集+oplog足够
  2. 超大规模:文件系统快照+延迟副本
  3. 混合架构:考虑MongoDB Atlas的云服务

记住三个关键数字:

  • oplog至少保留72小时
  • 备份验证频率不低于每周1次
  • 恢复演练每季度必须做