备份分片集群必须通过mongos而非直连shard,否则丢失路由元数据;恢复前须清空config server元数据;python脚本需设超时、权限及退出码检查;增量备份不可靠,应坚持全量备份加人工恢复验证。

备份分片集群必须连接到mongos,不能直连shard节点
直接用 mongodump 连某个 shard 的 mongod 进程,只会备份该分片的局部数据,丢失路由信息(config.shards、config.databases、config.collections)和 chunk 分布元数据,导致恢复后无法正确路由查询。正确做法是统一通过 mongos 实例发起备份,它会协调所有分片并自动拉取 config server 数据。
实操建议:
- 确保
mongos已启动且能访问全部shard和config server(检查mongos --version与集群版本兼容) - 使用
mongodump --host <mongos_host>:<port> --username <user> --password <pwd> --authenticationDatabase admin -o /backup/path</pwd></user></port></mongos_host> - 务必加上
--forceTableScan(MongoDB 4.4+),避免因某些集合无 _id 索引导致mongodump跳过 - 不要加
--oplog:分片集群的 oplog 是每个 shard 独立的,mongos不提供全局 oplog 接口,启用会报错cannot use --oplog against a sharded cluster
恢复前必须清空目标集群的 config server 元数据
用 mongorestore 恢复到新集群或重搭环境时,如果 config server 中还残留旧的 shards、databases 或 collections 记录,会导致新数据无法注册、chunk 迁移失败甚至 mongos 启动卡住。不能依赖 mongorestore 自动覆盖——它只写入集合数据,不清理旧元数据。
实操建议:
- 先停掉所有
mongos和shard进程,只保留 config server 可写 - 用
mongo连 config server 执行:db.shards.remove({}); db.databases.remove({}); db.collections.remove({}); db.chunks.remove({}); - 再启动
shard节点,最后启动mongos,确保它们能成功注册 - 最后运行
mongorestore --host <mongos_host>:<port> --username <user> --password <pwd> --authenticationDatabase admin /backup/path</pwd></user></port></mongos_host>
Python 脚本需显式处理分片集群特有的权限与超时
普通单机备份脚本用 subprocess.run 调 mongodump 往往失败,因为分片集群备份耗时更长(尤其跨网络)、需要更高权限(clusterAdmin 或 root),且 config server 默认限制写入频率。
实操建议:
- 在 Python 中用
subprocess.run时必须设timeout=3600(至少 1 小时),避免因大库备份中断 - 用户必须拥有
clusterAdmin角色(仅backup角色不够),验证方式:db.runCommand({connectionStatus: 1}).authInfo.roles - 为防 config server 写入被限流,可在
mongos启动参数中加--setParameter maxConns=10000(视硬件调整) - 脚本中加入退出码检查:
if result.returncode != 0:就记录result.stderr并告警,别只看 stdout
增量备份不可靠,必须定期全量 + 人工验证恢复流程
分片集群没有安全可靠的增量备份机制。虽然可以对每个 shard 单独 dump oplog 并按时间戳截断,但无法保证所有 shard 的 oplog 时间线严格对齐,mongorestore --oplogReplay 在分片环境下会跳过 config server 操作,导致元数据与数据状态不一致。
实操建议:
- 放弃基于 oplog 的“增量”幻想,用定时全量备份(例如每天一次)+ 压缩归档(
gzip)控制体积 - 每周选一个备份集,在隔离环境执行完整恢复流程(含 config server 清理、shard 重注册、mongos 启动、简单读写验证)
- 验证重点不是“有没有报错”,而是查
sh.status()输出是否显示所有数据库已分片、chunk 分布均匀、无jumbo chunk
真正容易被忽略的是 config server 的数据一致性——它不参与常规读写负载,出问题时往往静默,直到某次恢复才暴露。每次备份后,建议脚本自动执行 mongo <config_host>/config --eval "printjson(db.shards.count())"</config_host> 并比对历史值。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











