MongoDB 8.0 复制集、分片、备份恢复与生产排障
MongoDB 的生产运维不能只关注“服务进程是否存活”。真正决定可靠性的,是副本集多数派、写关注、读关注、选举、Oplog 窗口、分片元数据、Balancer、索引、备份一致性和恢复演练共同形成的闭环。本文以 MongoDB 8.0 为背景,但尽量采用跨小版本有效的方法,帮助运维人员建立从架构设计到事故恢复的完整路径。
数据库操作具有高风险。重配置副本集、调整成员优先级、强制重新配置、删除分片、清空 Oplog、恢复快照和执行全量导入前,必须确认备份、业务窗口、回滚路线及当前 Primary 身份。不要在生产环境直接复制示例中的主机名、密码和参数。
一、先把可靠性目标写清楚
上线前至少确认以下问题:
- RPO:允许最多丢失多少秒或多少个事务;
- RTO:主节点、机房或整个集群故障后多久恢复服务;
- 写入是否必须获得多数派确认;
- 读取是否允许读到旧数据,是否允许从 Secondary 读取;
- 数据量、峰值写入速率、工作集、索引规模和未来增长率;
- 单机房、同城双机房还是异地灾备;
- 备份保留周期、恢复粒度和演练频率;
- 是否存在跨文档事务、全局唯一约束或大对象需求。
副本集解决节点故障与自动选主,分片解决容量和吞吐扩展,备份解决误删除、逻辑损坏、勒索与历史恢复。三者互不替代。
二、复制集的正确生产拓扑
生产副本集通常至少三个投票成员,并分布在独立故障域。三个成员放在同一宿主机、同一存储阵列或同一交换机下,只是“进程冗余”,并不是故障域冗余。
应用
└─ MongoDB Driver(维护拓扑与重试)
├─ Primary:接收写入
├─ Secondary A:复制并可参与选举
└─ Secondary B:复制并可参与选举
仲裁节点 Arbiter 不保存数据,只参与投票。它能降低硬件成本,却会减少数据副本数,并可能在网络分区时形成不理想的多数派组合。重要业务优先采用数据节点,不要把 Arbiter 当成“第三份数据”。
检查基线:
rs.status()
rs.conf()
rs.printReplicationInfo()
rs.printSecondaryReplicationInfo()
db.adminCommand({ replSetGetStatus: 1 })
重点观察成员状态、选举任期、最后应用时间、复制源、心跳错误、回滚历史和 Oplog 首尾时间。
三、写关注、读关注与一致性
writeConcern 决定一次写入在返回成功前需要获得多少确认;readConcern 决定读取的数据可见性;readPreference 决定从哪个成员读取。三者组合决定延迟、可用性与一致性边界。
db.orders.insertOne(
{ orderId: "demo-001", status: "created" },
{ writeConcern: { w: "majority", j: true, wtimeout: 5000 } }
)
生产中需要特别避免:
- 业务以为写入已安全,但客户端只使用
w:1; - 从 Secondary 读取后立即验证刚写入的数据,误判为丢失;
- 网络延迟时无限等待,没有
wtimeout和请求超时; - 驱动连接串只写一个地址,失去拓扑发现能力;
- 在应用层盲目重试非幂等写入,造成重复订单。
多数派确认降低已确认写入在故障切换时回滚的概率,但不能替代备份,也不能消除应用重复提交问题。
四、Oplog 容量与复制延迟
Oplog 是有限大小的循环集合。Secondary 落后时间超过 Oplog 窗口后,将无法继续增量追赶,需要重新同步。容量规划应按高峰写入速率与最长可接受中断时间计算,并保留增长余量。
db.getSiblingDB("local").oplog.rs.stats()
db.getSiblingDB("local").oplog.rs.find().sort({ $natural: 1 }).limit(1)
db.getSiblingDB("local").oplog.rs.find().sort({ $natural: -1 }).limit(1)
复制延迟常见原因:磁盘延迟、长事务、大批量更新、索引过多、Secondary 同时承担报表、网络丢包、流量整形、CPU 饱和或 Oplog 应用线程受限。排查时区分“Primary 产生得太快”“网络拉取得太慢”和“Secondary 回放得太慢”。
五、选举、维护与滚动操作
选举发生时会出现短暂写中断,客户端必须使用支持重试写入和服务发现的官方驱动,并设置合理的 server selection、socket 和连接超时。维护前不要直接关机,应先确认成员健康、复制延迟和多数派。
推荐滚动顺序:
- 先处理 Secondary;
- 每次只处理一个成员;
- 等待其恢复为健康 Secondary 并追平;
- 必要时对 Primary 执行受控 step down;
- 处理原 Primary;
- 验证连接、写入、读取和告警。
rs.stepDown(60)
rs.stepDown() 会影响写服务,必须在应用具备重连能力且已确认健康候选节点时使用。不要把优先级改成 0 当作日常切换按钮。
六、分片集群设计
分片集群包含 mongos、Config Server Replica Set 和多个 Shard Replica Set。分片键一旦选择不当,后续迁移成本很高。
好的分片键通常具备:
- 较高基数;
- 写入分布均匀;
- 支持主要查询条件;
- 不产生持续单调热点;
- 不让单个租户或时间段无限增长;
- 能控制跨分片查询和跨分片事务比例。
sh.status()
sh.getBalancerState()
db.adminCommand({ balancerStatus: 1 })
db.collection.getShardDistribution()
不要只看 Chunk 数量。还要看每个分片的数据量、写入量、热点、迁移队列、Jumbo Chunk、孤儿文档、Config Server 健康和 mongos 版本一致性。
七、Balancer 与数据迁移
Balancer 用于重新分布数据,但迁移会消耗源端、目标端和网络资源。业务高峰出现大量迁移时,延迟可能升高。运维应设置迁移窗口、监控迁移失败和剩余不均衡程度,而不是长期关闭 Balancer。
分片下线前必须让数据完全迁出,确认 draining 状态结束,并验证数据库 Primary Shard。强制删除仍有数据的分片会造成不可恢复风险。
八、索引与查询治理
索引既提升读取,也增加写放大、内存和磁盘占用。治理时关注:
- 查询是否命中合理索引;
- 复合索引字段顺序是否符合等值、排序和范围模式;
- 是否存在大量未使用或重复前缀索引;
- 数组字段是否形成超大多键索引;
- 排序是否在内存或磁盘执行;
- 慢查询是否来自扫描过多文档、返回过多字段或跨分片散射。
db.orders.find({ tenantId: 7, status: "open" })
.sort({ createdAt: -1 })
.explain("executionStats")
检查 totalKeysExamined、totalDocsExamined、nReturned、执行阶段和是否发生阻塞排序。不要仅凭“有 IXSCAN”就判断查询健康。
九、备份策略与一致性
自建部署可采用 Ops Manager/Cloud Manager、存储快照或 mongodump。逻辑导出更适合较小数据集和迁移;大规模集群更关注一致快照、持续 Oplog 与时间点恢复。
文件系统快照要求数据文件与 Journal 的一致性边界正确。分片集群还涉及所有 Shard、Config Server 与 Balancer 状态,不能随意对不同节点在不同时间各拍一张快照后声称“全局一致”。
mongodump --uri='mongodb://user@host1,host2,host3/app?replicaSet=rs0' \
--archive=app.archive --gzip
mongorestore --uri='mongodb://restore-host/app' \
--archive=app.archive --gzip --dryRun
恢复必须先在隔离环境验证。备份成功的判断不应只是“文件存在”,而应包含可读取、校验通过、能启动、能完成业务抽样和满足目标 RTO。
十、常见故障处理
Primary 不可用
- 检查是否还有多数派;
- 检查网络、时间同步、磁盘和节点存活;
- 查看驱动是否发现新 Primary;
- 不要在网络分区未解除时强制两边各自成主;
- 必要时隔离旧主,避免脑裂式双写。
Secondary 长期 RECOVERING
检查初始同步日志、磁盘空间、源节点负载、网络带宽、Oplog 窗口和数据文件权限。如果数据规模很大,应从健康成员的受控快照重建,而不是反复触发全量同步冲击生产。
磁盘快速增长
区分数据、索引、Journal、诊断日志、审计日志和临时文件。TTL 删除不会立即让操作系统看到等量空间回收,压缩或重写集合也需要额外空间和维护窗口。
大量连接与超时
检查驱动连接池、应用实例数、连接复用、认证耗时、DNS、TLS、服务发现和慢请求。不要简单提高连接上限掩盖连接泄漏。
十一、监控与告警基线
至少监控:
- 副本集成员状态、Primary 变化和选举次数;
- 复制延迟与 Oplog 时间窗口;
- 连接数、操作队列和锁;
- WiredTiger Cache 使用、脏页和驱逐;
- 查询延迟、扫描/返回比、慢查询;
- 磁盘容量、IOPS、延迟和文件系统错误;
- 分片数据分布、迁移和 Jumbo Chunk;
- 备份时长、备份新鲜度和恢复演练结果。
告警要带上集群、成员、角色、时间窗口和处置入口。仅告警“MongoDB down”无法支持快速判断。
十二、生产变更与恢复清单
变更前:确认健康多数派、复制追平、备份有效、容量充足、驱动兼容、回滚版本和观察窗口。变更中:每次只改一个故障域,持续观察选举、延迟、错误率与业务指标。变更后:验证写入、读取、索引、TTL、备份和告警,并记录实际结果。
恢复演练至少每季度进行一次,随机抽取备份恢复到隔离环境,核对集合、文档数、索引、权限、业务关键记录和恢复耗时。恢复能力来自演练,不来自备份任务的绿色图标。
参考资料
- MongoDB Manual:
https://www.mongodb.com/docs/manual/ - MongoDB 8.0 Backup Methods:
https://www.mongodb.com/docs/v8.0/core/backups/ - MongoDB Replica Set Deployment Architectures:
https://www.mongodb.com/docs/manual/core/replica-set-architectures/ - MongoDB Sharding:
https://www.mongodb.com/docs/manual/sharding/