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 和连接超时。维护前不要直接关机,应先确认成员健康、复制延迟和多数派。

推荐滚动顺序:

  1. 先处理 Secondary;
  2. 每次只处理一个成员;
  3. 等待其恢复为健康 Secondary 并追平;
  4. 必要时对 Primary 执行受控 step down;
  5. 处理原 Primary;
  6. 验证连接、写入、读取和告警。
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 不可用

  1. 检查是否还有多数派;
  2. 检查网络、时间同步、磁盘和节点存活;
  3. 查看驱动是否发现新 Primary;
  4. 不要在网络分区未解除时强制两边各自成主;
  5. 必要时隔离旧主,避免脑裂式双写。

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/
Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-11-03 16:23:43

results matching ""

    No results matching ""