← 返回首页

MongoDB 运维维护手册

面向 DBA / 运维工程师,聚焦生产环境的部署架构、监控告警、性能调优、备份恢复、故障排查、容量规划与版本升级。所有命令均基于 MongoDB 7.0 + CentOS 7 + Docker 环境。


目录

  1. 生产部署架构选型
  2. Docker 部署形态(单机/副本集/分片集群)
  3. 监控体系搭建
  4. 性能调优
  5. 备份与恢复
  6. 安全加固
  7. 日志管理
  8. 副本集运维操作
  9. 容量规划
  10. 版本升级与回滚
  11. 故障排查手册
  12. 应急预案
  13. 日常巡检清单

1. 生产部署架构选型

架构 适用场景 节点数 高可用 水平扩展 运维复杂度
单机 开发/测试 1 无 无 低
副本集 (Replica Set) 中小规模生产 3+ 有 无 中
分片集群 (Sharded Cluster) 大数据量/高并发 9+ 有 有 高

选型决策

  • 数据量 < 500GB,QPS < 5000 → 副本集(3 节点)
  • 数据量 500GB-3TB,单集合写入瓶颈 → 分片集群
  • 数据量 > 3TB → 必须分片

副本集 vs 分片集群核心区别

  • 副本集:所有节点存全量数据,解决"高可用",不解决"容量"
  • 分片集群:数据分散到多个 shard,每个 shard 是副本集,同时解决"高可用 + 容量"

生产环境最低标准:3 节点副本集(1 Primary + 2 Secondary),可容忍 1 节点故障。


2. Docker 部署形态

本节覆盖三种部署形态,按数据量和可用性需求递进:单机(测试)→ 副本集(生产标准)→ 分片集群(大数据量)。

形态 节点数 高可用 水平扩展 适用
单机 1 无 无 开发/测试/学习
副本集 3+ 有 无 中小规模生产
分片集群 10+ 有 有 大数据量/高并发

2.1 单机部署(开发/测试)

仅用于开发/测试/学习。生产环境禁止单机——无高可用、无数据冗余,宕机即丢服务,且无法做 point-in-time 恢复。

docker-compose 配置

# /data/mongo/standalone/docker-compose.yml
version: "3.8"

services:
  mongodb:
    image: mongo:7.0
    container_name: mongodb
    restart: always
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: YourStrongPassword123
    volumes:
      - /data/mongo/standalone/db:/data/db
      - /data/mongo/standalone/config:/data/configdb
      - /data/mongo/standalone/log:/var/log/mongodb
    command:
      - "--bind_ip_all"
      - "--auth"
      - "--wiredTigerCacheSizeGB=2"    # 建议: 容器内存的 50-60%
    deploy:
      resources:
        limits:
          memory: 4G
    networks:
      - mongo-net

networks:
  mongo-net:
    driver: bridge

启动与连接

# 创建目录
mkdir -p /data/mongo/standalone/{db,config,log}

# 启动
cd /data/mongo/standalone
docker compose up -d

# 查看状态
docker ps | grep mongodb
docker logs mongodb

# 进入 shell
docker exec -it mongodb mongosh -u root -p YourStrongPassword123

# 远程连接
mongosh "mongodb://root:YourStrongPassword123@服务器IP:27017/admin"

单机运维注意

  • 无故障转移:mongod 进程挂掉即服务中断,依赖 restart: always 自动拉起
  • 备份限制:只能用 mongodump(无 oplog,不能加 --oplog,不能恢复到任意时间点)
  • 可平滑升级为副本集:加 --replSet 参数重启 → rs.initiate() → 再加入其他节点
  • 数据量建议 < 10GB:超过建议直接上副本集
  • 监控仍需开启:单机也要监控连接数、内存、磁盘,参考第 3 节

2.2 副本集部署(生产标准)

生产环境最低标准:3 节点(1 Primary + 2 Secondary),可容忍 1 节点故障,自动故障转移。

2.2.1 docker-compose 部署 3 节点副本集

# /data/mongo/compose/docker-compose.yml
version: "3.8"

services:
  mongo1:
    image: mongo:7.0
    container_name: mongo1
    restart: always
    hostname: mongo1
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: YourStrongPassword123
    volumes:
      - /data/mongo/node1/db:/data/db
      - /data/mongo/node1/config:/data/configdb
      - /data/mongo/node1/log:/var/log/mongodb
    command: ["--replSet", "rs0", "--bind_ip_all", "--auth"]
    networks:
      - mongo-net

  mongo2:
    image: mongo:7.0
    container_name: mongo2
    restart: always
    hostname: mongo2
    ports:
      - "27018:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: YourStrongPassword123
    volumes:
      - /data/mongo/node2/db:/data/db
      - /data/mongo/node2/config:/data/configdb
      - /data/mongo/node2/log:/var/log/mongodb
    command: ["--replSet", "rs0", "--bind_ip_all", "--auth"]
    networks:
      - mongo-net

  mongo3:
    image: mongo:7.0
    container_name: mongo3
    restart: always
    hostname: mongo3
    ports:
      - "27019:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: YourStrongPassword123
    volumes:
      - /data/mongo/node3/db:/data/db
      - /data/mongo/node3/config:/data/configdb
      - /data/mongo/node3/log:/var/log/mongodb
    command: ["--replSet", "rs0", "--bind_ip_all", "--auth"]
    networks:
      - mongo-net

networks:
  mongo-net:
    driver: bridge

2.2.2 初始化副本集

# 启动所有节点
cd /data/mongo/compose
docker compose up -d

# 进入 mongo1 初始化副本集
docker exec -it mongo1 mongosh -u root -p YourStrongPassword123
// 初始化副本集(需用容器名,因为是 Docker 网络)
rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "mongo1:27017", priority: 2 },
    { _id: 1, host: "mongo2:27017", priority: 1 },
    { _id: 2, host: "mongo3:27017", priority: 1 }
  ]
})

// 查看副本集状态
rs.status()

// 查看是否已选出 Primary
rs.isMaster()

2.2.3 创建业务管理员账号

初始化副本集后,在 Primary 上创建:

use admin
db.createUser({
  user: "admin",
  pwd: "AdminStrongPassword456",
  roles: [{ role: "root", db: "admin" }]
})

2.2.4 连接副本集(推荐)

# 连接字符串带 replicaSet 参数
mongosh "mongodb://root:YourStrongPassword123@mongo1:27017,mongo2:27017,mongo3:27017/admin?replicaSet=rs0"

# 应用程序连接串(驱动会自动发现所有节点,故障时自动切换)
mongodb://user:pass@mongo1:27017,mongo2:27017,mongo3:27017/mydb?replicaSet=rs0&authSource=admin

关键:连接串必须列出多个节点,驱动才能在 Primary 切换后自动重连新 Primary。


2.3 分片集群部署(大数据量)

当单库数据 > 3TB、单集合 > 500GB、或单机写入 QPS 扛不住时,需用分片集群水平扩展。每个 shard 内部本身就是副本集,兼顾高可用与扩展性。

2.3.1 组件说明

组件 作用 数量 说明
mongos 路由入口 ≥2(生产) 应用只连 mongos,不直连 shard
config server 元数据 & 路由表 3(副本集) 记录 chunk 分布,必须高可用
shard 存数据 ≥2(各为副本集) 每个 shard 是独立副本集

本节部署最小可用分片集群:1 mongos + 1 config-rs(3节点) + 2 shard-rs(各3节点) = 10 个容器。

2.3.2 docker-compose 配置

完整配置见独立文件 mongo-sharded-docker-compose.yml,核心结构:

# config server(3 节点副本集,端口 27019)
cfg1/cfg2/cfg3:
  command: ["--configsvr", "--replSet", "cfgReplSet", "--bind_ip_all", "--auth"]

# shard(每个 3 节点副本集,端口 27018)
shard1a/1b/1c:
  command: ["--shardsvr", "--replSet", "shard1ReplSet", "--bind_ip_all", "--auth"]
shard2a/2b/2c:
  command: ["--shardsvr", "--replSet", "shard2ReplSet", "--bind_ip_all", "--auth"]

# mongos 路由(端口 27017)
mongos:
  command: ["--configdb", "cfgReplSet/cfg1:27019,cfg2:27019,cfg3:27019", "--bind_ip_all"]

关键启动参数:--configsvr(标记为配置服务器)、--shardsvr(标记为分片节点)。mongos 不存数据,通过 --configdb 指向 config 副本集。

2.3.3 初始化分片集群

# 0. 创建目录并启动
mkdir -p /data/mongo/sharded/{cfg1,cfg2,cfg3,shard1a,shard1b,shard1c,shard2a,shard2b,shard2c}/{db,config}
cp mongo-sharded-docker-compose.yml /data/mongo/sharded/docker-compose.yml
cd /data/mongo/sharded
docker compose up -d
sleep 10   # 等待节点就绪
# 1. 初始化 config server 副本集(在 cfg1 执行)
docker exec cfg1 mongosh -u root -p YourStrongPassword123 \
  --authenticationDatabase admin --eval '
  rs.initiate({
    _id: "cfgReplSet",
    configsvr: true,
    members: [
      { _id: 0, host: "cfg1:27019" },
      { _id: 1, host: "cfg2:27019" },
      { _id: 2, host: "cfg3:27019" }
    ]
  })
'
# 2. 初始化 shard1 副本集(在 shard1a 执行)
docker exec shard1a mongosh -u root -p YourStrongPassword123 \
  --authenticationDatabase admin --eval '
  rs.initiate({
    _id: "shard1ReplSet",
    members: [
      { _id: 0, host: "shard1a:27018" },
      { _id: 1, host: "shard1b:27018" },
      { _id: 2, host: "shard1c:27018" }
    ]
  })
'

# 3. 初始化 shard2 副本集(在 shard2a 执行)
docker exec shard2a mongosh -u root -p YourStrongPassword123 \
  --authenticationDatabase admin --eval '
  rs.initiate({
    _id: "shard2ReplSet",
    members: [
      { _id: 0, host: "shard2a:27018" },
      { _id: 1, host: "shard2b:27018" },
      { _id: 2, host: "shard2c:27018" }
    ]
  })
'
sleep 15   # 等待所有副本集选出 Primary
# 4. 连接 mongos,添加分片到集群
docker exec mongos mongosh --eval '
  sh.addShard("shard1ReplSet/shard1a:27018,shard1b:27018,shard1c:27018")
  sh.addShard("shard2ReplSet/shard2a:27018,shard2b:27018,shard2c:27018")
  sh.status()
'

2.3.4 启用分片

// 连接 mongos
// docker exec -it mongos mongosh

// 1. 对数据库启用分片
sh.enableSharding("mydb")

// 2. 选择 shard key(至关重要!选错无法更改)
//    原则: 高基数(值多) + 低频率(分布均匀) + 非单调递增
//    常用: hashed 分片(均匀打散)或 ranged 分片(范围查询友好)

// 3. 对集合分片前,必须先建索引
use mydb
db.orders.createIndex({ userId: "hashed" })       // hashed 分片
// 或 db.orders.createIndex({ createdAt: 1 })       // ranged 分片

// 4. 启用集合分片
sh.shardCollection("mydb.orders", { userId: "hashed" })

// 5. 查看分片状态 & 数据分布
sh.status()
db.orders.getShardDistribution()

2.3.5 连接分片集群

# 应用只连 mongos(端口 27017),绝不直连 shard
mongosh "mongodb://服务器IP:27017/mydb"

# 带认证
mongosh "mongodb://user:pass@服务器IP:27017/mydb?authSource=admin"

# 生产多 mongos 连接串(故障自动切换)
mongodb://mongos1:27017,mongos2:27017/mydb

2.3.6 分片集群运维要点

// 集群状态总览
sh.status()                         // 所有 shard、chunk 分布
sh.balancer.status()                // 均衡器状态
sh.isBalancerRunning()              // 均衡器是否在迁移 chunk

// 维护窗口暂停均衡(避免迁移影响性能)
sh.disableBalancing()               // 暂停
sh.enableBalancing()                // 恢复
sh.setBalancerState(false)          // 同上

// 集合分布详情
db.orders.getShardDistribution()    // 各 shard 数据量
db.orders.stats().sharded           // 是否已分片

// 添加新分片(扩容)
sh.addShard("shard3ReplSet/shard3a:27018,shard3b:27018,shard3c:27018")
// 添加后均衡器自动迁移 chunk 到新 shard

// 移除分片(会先迁移数据,耗时)
db.adminCommand({ removeShard: "shard2ReplSet" })
// 反复执行直到返回 completed,期间可查迁移进度

shard key 选择是分片集群最关键的决策:
- 选错会导致数据倾斜(个别 shard 过载)或 jumbo chunk
- MongoDB 5.0 起支持 refineCollectionShardKey 微调,但不能完全更换
- 4.4 之前完全无法更改,只能新建集合迁移数据
- 推荐:{ userId: "hashed" }(高基数、均匀)或 { _id: "hashed" }

何时分片:先确认瓶颈是"容量"还是"性能"。如果是单集合查询慢,优先加索引;如果是连接数/CPU 瓶颈,先升级硬件。分片解决的是水平扩展,不是万能药。


2.4 三种部署形态对照

维度 单机 副本集 分片集群
节点数 1 3+ 10+
高可用 无(进程级 restart) 自动故障转移 10-30s shard 级故障转移
数据冗余 无 全量复制 分片内全量复制
容量上限 单机磁盘 单机磁盘 ×1 理论无限
写扩展性 单点 单 Primary 写 多 shard 并行写
备份方式 mongodump mongodump --oplog / 快照 每 shard 独立备份 / mongodump
Point-in-time 恢复 不支持 支持(oplog) 支持(每 shard 的 oplog)
运维复杂度 低 中 高
适用阶段 开发测试 中小生产 大数据量生产
升级路径 → 副本集 → 分片集群 -

建议路径:测试用单机 → 生产上副本集 → 数据量增长后分片。可平滑升级,无需推倒重来。


3. 监控体系搭建

3.1 核心监控指标(必看)

维度 指标 获取方式 告警阈值
连接数 current connections serverStatus().connections.current > maxConn × 80%
内存 cache hit ratio wiredTiger.cache 计算 < 95%
内存 pages evicted wiredTiger.cache.evicted 持续增长告警
复制 replication lag rs.printSecondaryReplicationInfo() > 10s
复制 node state rs.status() 中 stateStr 非 PRIMARY/SECONDARY
性能 slow queries profile 集合 / logs > 100ms
性能 active connections serverStatus().globalLock.activeClients > 1000
磁盘 disk usage df -h > 80%
磁盘 disk IOPS iostat -x 1 util > 90%
队列 read/write queue serverStatus().globalLock.currentQueue 持续 > 0

3.2 关键诊断命令

服务器整体状态

// 完整服务器状态(输出很大)
db.serverStatus()

// 精简查看关键指标
db.serverStatus().connections
db.serverStatus().opcounters          // 各操作 QPS
db.serverStatus().globalLock          // 锁和队列
db.serverStatus().wiredTiger.cache    // 缓存
db.serverStatus().mem                 // 内存
db.serverStatus().metrics.query       // 查询统计

// 当前版本和运行时间
db.serverStatus().version
db.serverStatus().uptime

副本集状态

// 副本集完整状态
rs.status()

// 简洁版:各节点延迟
rs.printSecondaryReplicationInfo()

// oplog 信息(窗口大小很重要)
rs.printReplicationInfo()

// 是否是 Primary
rs.isMaster()

当前活跃操作

// 查看所有活跃操作
db.currentOp({ active: true })

// 只看运行超过 1 秒的操作
db.currentOp({
  active: true,
  secs_running: { $gte: 1 }
})

// 杀掉指定操作
db.killOp("opid")

慢查询分析

// 开启慢查询日志(记录 > 100ms 的操作)
db.setProfilingLevel(1, { slowms: 100 })

// 查看级别
db.getProfilingStatus()

// 查看慢查询记录(存在 system.profile 集合)
db.system.profile.find().sort({ ts: -1 }).limit(10)

// 查询最慢的 5 个操作
db.system.profile.find()
  .sort({ millis: -1 })
  .limit(5)
  .forEach(op => printjson({
    op: op.op,
    ns: op.ns,
    millis: op.millis,
    query: op.command
  }))

3.3 监控方案选型

方案 说明 适用
MongoDB Cloud Monitor 官方免费,需联网上报 云上/可联网
Prometheus + Grafana mongodb_exporter 采集 自建机房推荐
Percona PMM 开源数据库监控平台 多种数据库混合
Zabbix + 自定义脚本 传统运维已有 Zabbix 已有 Zabbix 体系

Prometheus + mongodb_exporter 部署

# 在 docker-compose 中加入 exporter
  mongo-exporter:
    image: percona/mongodb_exporter:latest
    container_name: mongo-exporter
    restart: always
    ports:
      - "9216:9216"
    environment:
      MONGODB_URI: "mongodb://root:YourStrongPassword123@mongo1:27017/admin?authSource=admin"
    depends_on:
      - mongo1
    networks:
      - mongo-net

Grafana 推荐仪表盘 ID:7353(MongoDB Overview)、16490(副本集详情)。

3.4 告警规则示例(Prometheus AlertManager)

groups:
  - name: mongodb
    rules:
      - alert: MongoDBDown
        expr: mongodb_up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "MongoDB 实例宕机"

      - alert: MongoDBReplicationLag
        expr: mongodb_rs_members_replication_lag > 10
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "复制延迟超过 10 秒"

      - alert: MongoDBConnectionsHigh
        expr: mongodb_ss_connections{conn_type="current"} / on(instance) mongodb_ss_connections{conn_type="available"} > 0.8
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "连接数超过 80%"

      - alert: MongoDBDiskSpaceLow
        expr: (1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) > 0.8
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "磁盘使用率超过 80%"

4. 性能调优

4.1 WiredTiger 存储引擎调优

WiredTiger 是 MongoDB 3.2+ 默认引擎,核心参数是缓存大小。

// 查看当前缓存配置
db.serverStatus().wiredTiger.cache

// 关键指标:
// "maximum bytes configured"  - 配置的最大缓存
// "bytes currently in the cache" - 当前使用
// "pages evicted by application threads" - 应用线程触发的驱逐(高则内存不足)

通过启动参数调整缓存

# docker-compose command 中加入
command:
  - "--replSet"
  - "rs0"
  - "--bind_ip_all"
  - "--auth"
  - "--wiredTigerCacheSizeGB=4"    # 建议: 物理内存的 50%-60%

经验值:缓存 = 物理内存 × 0.6。留 30% 给操作系统文件缓存,10% 给其他进程。

4.2 索引优化

索引使用分析

// 查看集合所有索引
db.users.getIndexes()

// 索引大小(评估内存占用)
db.users.stats().indexSizes

// 分析查询是否走索引
db.users.find({ name: "张三" }).explain("executionStats")

// 关键看:
// winningPlan.stage = "IXSCAN"  → 走索引(好)
// winningPlan.stage = "COLLSCAN" → 全表扫描(坏)
// executionStats.totalDocsExamined  → 扫描文档数
// executionStats.nReturned          → 返回文档数
// 理想: totalDocsExamined ≈ nReturned

索引设计原则

// 1. ESR 原则: Equality(等值) > Sort(排序) > Range(范围)
// 复合索引字段顺序按 E-S-R 排列
db.orders.createIndex({ status: 1, createdAt: -1, amount: 1 })
// status 等值查询, createdAt 排序, amount 范围查询

// 2. 覆盖索引(查询字段全在索引里,无需回表)
db.users.createIndex({ name: 1, age: 1, email: 1 })
db.users.find({ name: "张三" }, { age: 1, email: 1, _id: 0 })
// 此查询被索引覆盖,不读文档

// 3. 删除未使用索引(写入有开销)
db.users.aggregate([{ $indexStats: {} }])
// 查看各索引使用次数,删除使用为 0 的

4.3 慢查询治理

// 1. 开启 profile
db.setProfilingLevel(1, { slowms: 100, sampleRate: 1 })

// 2. 定期分析 TOP 10 慢查询
db.system.profile.aggregate([
  { $group: {
      _id: { op: "$op", ns: "$ns", query: "$command" },
      count: { $sum: 1 },
      avgMillis: { $avg: "$millis" },
      maxMillis: { $max: "$millis" }
  }},
  { $sort: { avgMillis: -1 } },
  { $limit: 10 }
])

// 3. 生产环境 profile 集合会增长,定期清理
db.system.profile.drop()
db.setProfilingLevel(1, { slowms: 100 })

4.4 连接池优化

# mongod.conf 或启动参数
net:
  maxIncomingConnections: 20000    # 默认 65535,按需调小防过载

# 应用端连接池(以 Node.js 驱动为例)
# maxPoolSize: 100 (默认)
# minPoolSize: 10
# maxIdleTimeMS: 30000

经验:单个 mongod 实例 maxPoolSize 建议 100-200,不要无限大。连接数过多会消耗内存和上下文切换。

4.5 系统层面优化

# 1. 文件描述符限制(重要)
cat >> /etc/security/limits.conf <<'EOF'
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
EOF

# 2. 关闭透明大页(THP,MongoDB 推荐 disabled)
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 持久化(重启生效)
cat >> /etc/rc.local <<'EOF'
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
EOF
chmod +x /etc/rc.local

# 3. 文件系统推荐 XFS(优于 ext4)
# 4. 磁盘调度器推荐 deadline / noop(SSD)
# 5. 关闭 atime 挂载选项
mount -o remount,noatime /data

4.6 Docker 容器特殊注意

# 1. 限制容器内存,防止 OOM 影响其他服务
deploy:
  resources:
    limits:
      memory: 8G

# 2. WiredTiger 缓存要小于容器内存限制
# 容器 8G → 缓存设 4G (--wiredTigerCacheSizeGB=4)

# 3. 数据目录用 bind mount 而非 volume,性能更好
volumes:
  - /data/mongo/node1/db:/data/db

# 4. 网络用 host 模式可减少一层 NAT(仅单机时)
# network_mode: "host"

5. 备份与恢复

5.1 备份方案对比

方案 优点 缺点 适用
mongodump 简单、跨版本 慢、占空间、非一致性快照 小库 < 50GB
文件系统快照 快、一致性好 需 LVM/云盘快照 大库首选
文件拷贝 快 需停 db.lockDown 应急
oplog 增量 可恢复到任意时间点 需配合全量 精细恢复

5.2 mongodump 备份(小库)

# 全量备份(指定副本集,从 Secondary 读减少 Primary 压力)
docker exec mongo2 mongodump \
  -u root -p YourStrongPassword123 \
  --authenticationDatabase admin \
  --oplog \
  --gzip \
  --archive=/data/backup/full_$(date +%Y%m%d).gz

# 复制到宿主机
docker cp mongo2:/data/backup/full_$(date +%Y%m%d).gz /data/mongo/backup/

# 单库备份
docker exec mongo2 mongodump \
  -u root -p YourStrongPassword123 \
  --authenticationDatabase admin \
  -d mydb \
  --gzip \
  --out=/data/backup/mydb_$(date +%Y%m%d)

# 单集合备份
docker exec mongo2 mongodump \
  -u root -p YourStrongPassword123 \
  --authenticationDatabase admin \
  -d mydb -c users \
  --gzip \
  --out=/data/backup/users_$(date +%Y%m%d)

关键参数 --oplog:记录备份期间的 oplog,恢复时能保证一致性(仅副本集可用)。

5.3 mongorestore 恢复

# 全量恢复
docker cp /data/mongo/backup/full_20260727.gz mongo1:/data/restore/
docker exec mongo1 mongorestore \
  -u root -p YourStrongPassword123 \
  --authenticationDatabase admin \
  --oplogReplay \
  --gzip \
  --archive=/data/restore/full_20260727.gz

# 恢复单库(不覆盖已有数据用 --drop 先删后导)
docker exec mongo1 mongorestore \
  -u root -p YourStrongPassword123 \
  --authenticationDatabase admin \
  -d mydb --drop \
  --gzip \
  /data/restore/mydb_20260727/mydb

5.4 文件系统快照备份(大库推荐)

# 前提: 数据目录在 LVM 卷上

# 1. 在 Primary 上加锁(不中断读写,只刷盘)
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval '
  db.fsyncLock()
'

# 2. 创建 LVM 快照
lvcreate -L 10G -s -n mongo_snap /dev/vg0/mongo_data

# 3. 解锁
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval '
  db.fsyncUnlock()
'

# 4. 挂载快照并备份
mount /dev/vg0/mongo_snap /mnt/snap
tar -czf /backup/mongo_$(date +%Y%m%d).tar.gz -C /mnt/snap .
umount /mnt/snap
lvremove -f /dev/vg0/mongo_snap

云服务器可用云盘快照替代 LVM,更简单。先 fsyncLock,再打快照,再 fsyncUnlock。

5.5 定时备份脚本

#!/bin/bash
# /data/mongo/scripts/backup.sh
BACKUP_DIR="/data/mongo/backup"
DATE=$(date +%Y%m%d_%H%M%S)
KEEP_DAYS=7
SECONDARY="mongo2"

mkdir -p ${BACKUP_DIR}

echo "[$(date)] 开始备份..."
docker exec ${SECONDARY} mongodump \
  -u root -p YourStrongPassword123 \
  --authenticationDatabase admin \
  --oplog --gzip \
  --archive=/data/backup/full_${DATE}.gz

docker cp ${SECONDARY}:/data/backup/full_${DATE}.gz ${BACKUP_DIR}/
docker exec ${SECONDARY} rm /data/backup/full_${DATE}.gz

# 清理过期备份
find ${BACKUP_DIR} -name "full_*.gz" -mtime +${KEEP_DAYS} -delete

echo "[$(date)] 备份完成: ${BACKUP_DIR}/full_${DATE}.gz"
echo "[$(date)] 已清理 ${KEEP_DAYS} 天前备份"
# crontab 每天凌晨 2 点备份
crontab -e
# 0 2 * * * /data/mongo/scripts/backup.sh >> /data/mongo/logs/backup.log 2>&1

5.6 oplog 增量恢复(Point-in-Time Recovery)

# 场景: 误删数据,需要恢复到误操作前的时间点

# 1. 用全量备份恢复到一个新实例(隔离环境)
# 2. 查看误操作时间
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval '
  use local
  db.oplog.rs.find({
    ns: "mydb.users",
    op: "d"
  }).sort({ ts: -1 }).limit(5)
'

# 3. 用 mongorestore --oplogReplay --oplogLimit 恢复到指定时间点前
# oplogLimit 格式: timestamp:inc
mongorestore \
  --host new-mongo \
  --oplogReplay \
  --oplogLimit 1719000000:1 \
  --gzip --archive=full_20260726.gz

6. 安全加固

6.1 认证与授权

// 1. 启动必须带 --auth(已在 docker-compose 配置)
// 2. 最小权限原则: 业务用 readWrite,不用 root

use mydb
db.createUser({
  user: "appuser",
  pwd: passwordPrompt(),   // 交互式输入密码,不留在历史
  roles: [{ role: "readWrite", db: "mydb" }]
})

// 3. 只读用户(报表/分析)
db.createUser({
  user: "reporter",
  pwd: passwordPrompt(),
  roles: [{ role: "read", db: "mydb" }]
})

// 4. 查看所有用户
use admin
db.getUsers()

// 5. 定期审计用户权限
db.getUsers().forEach(u => {
  print(u.user + ": " + JSON.stringify(u.roles))
})

6.2 内置角色权限矩阵

角色 读 写 建索引 管用户 管库
read Y - - - -
readWrite Y Y - - -
dbAdmin Y Y Y - Y
userAdmin - - - Y -
dbOwner Y Y Y Y Y
root Y Y Y Y Y(所有库)

6.3 网络安全

# mongod.conf 限制绑定 IP
net:
  bindIp: 127.0.0.1,10.0.0.5   # 只绑定内网,不绑 0.0.0.0
  port: 27017

# 或 docker-compose
command: ["--bind_ip", "127.0.0.1,172.18.0.1"]
# 防火墙只允许应用服务器 IP
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.10" port port=27017 protocol=tcp accept'
firewall-cmd --reload

# 禁止公网暴露 27017(MongoDB 被勒索病毒扫描的重灾区)

6.4 TLS/SSL 加密传输

# 生成证书(或用企业 CA)
openssl req -newkey rsa:2048 -nodes -keyout mongodb.key -x509 -days 365 -out mongodb.crt
cat mongodb.key mongodb.crt > mongodb.pem

# docker-compose 启用 TLS
command:
  - "--tlsMode=requireTLS"
  - "--tlsCertificateKeyFile=/data/config/mongodb.pem"
volumes:
  - /data/mongo/certs:/data/config

6.5 审计日志(企业版功能,社区版替代方案)

// 社区版可用 profile 记录操作
db.setProfilingLevel(2)   // 记录所有操作(性能影响大,仅排查时用)

// 或用 mongod 启动参数开启审计(企业版)
auditLog:
  destination: file
  format: JSON
  path: /var/log/mongodb/audit.log

6.6 安全检查清单

  • [ ] 启动参数带 --auth
  • [ ] root 密码为强密码(16 位+,含大小写数字符号)
  • [ ] 业务用户最小权限(readWrite,非 root)
  • [ ] bindIp 不含 0.0.0.0(生产)
  • [ ] 防火墙限制来源 IP
  • [ ] 27017 端口不对公网开放
  • [ ] 开启 TLS 加密传输
  • [ ] 定期轮换密码
  • [ ] 禁用未使用的用户
  • [ ] 数据文件目录权限 600

7. 日志管理

7.1 日志位置与查看

# Docker 部署日志在容器内 /var/log/mongodb/mongod.log
docker exec mongo1 cat /var/log/mongodb/mongod.log

# 或通过 docker logs
docker logs --tail 100 mongo1

# 实时跟踪
docker logs -f mongo1

# 查找错误
docker logs mongo1 2>&1 | grep -i "error\|fatal\|warning"

7.2 日志级别调整

// 查看当前日志级别
db.getLogComponents()

// 临时提高某组件日志级别(1-5,越高越详细)
db.setLogLevel(2, "command")     // 命令日志
db.setLogLevel(2, "query")       // 查询日志
db.setLogLevel(1, "replication") // 复制日志

// 排查完恢复
db.setLogLevel(0, "command")

7.3 日志轮转

// MongoDB 内置日志轮转
db.adminCommand({ logRotate: 1 })

// 或配置启动参数定期轮转
// systemLog.logRotate: reopen
// + logrotate 配置
# /etc/logrotate.d/mongodb
/var/log/mongodb/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}

7.4 关键日志关键词

关键词 含义 处理
WT_CACHE_EVICT 缓存驱逐 内存不足,调大缓存
Replication lag 复制延迟 排查 Secondary 负载
Connection refused 连接拒绝 检查 ulimit / maxConn
Out of memory OOM 容器内存限制太小
E11000 duplicate key 唯一键冲突 应用层逻辑问题
election 发起选举 Primary 切换,检查原因
Index build 建索引中 可能影响性能,关注完成

8. 副本集运维操作

8.1 添加新节点

// 1. 新节点已用 --replSet rs0 启动且数据目录为空
// 2. 在 Primary 上执行
rs.add({ host: "mongo4:27017", priority: 1 })

// 查看同步进度
rs.status()
// 新节点 stateStr 会从 STARTUP → STARTUP2 → SECONDARY

8.2 移除节点

// 先降级 priority 避免选举抖动
cfg = rs.conf()
cfg.members[3].priority = 0
cfg.members[3].votes = 0
rs.reconfig(cfg)

// 等待稳定后移除
rs.remove("mongo4:27017")

8.3 手动切换 Primary(计划内维护)

// 方法1: stepDown(推荐,平滑切换)
// Primary 主动让位,60 秒内不重新竞选
rs.stepDown(60)

// 方法2: 调整 priority
cfg = rs.conf()
cfg.members[0].priority = 0   // 当前 Primary
cfg.members[1].priority = 2   // 目标节点
rs.reconfig(cfg)

// 切换后恢复 priority
cfg.members[0].priority = 2
cfg.members[1].priority = 1
rs.reconfig(cfg)

8.4 节点重新同步(数据不一致时)

// 1. 在有问题的 Secondary 上停止同步
// 进入该节点容器
docker exec -it mongo2 mongosh -u root -p YourStrongPassword123

// 2. 将节点改为 RECOVERING 状态
db.adminCommand({ replSetMaintenance: true })

// 3. 停止该节点
docker stop mongo2

// 4. 清空数据目录(宿主机)
rm -rf /data/mongo/node2/db/*

// 5. 重新启动
docker start mongo2

// 6. 节点会自动全量同步
rs.status()   // 观察 stateStr 变为 SECONDARY

8.5 调整 oplog 大小

// 查看当前 oplog 大小
use local
db.oplog.rs.stats().maxSize

// 调整(只增不减,需在 Primary 执行)
db.adminCommand({
  replSetResizeOplog: 1,
  size: 51200   // 单位 MB,这里设 50GB
})

oplog 大小建议:至少能容纳 24-48 小时的写入。可通过 rs.printReplicationInfo() 查看 oplog 窗口时长。

8.6 修改副本集配置

// 查看当前配置
rs.conf()

// 修改投票节点数 / 优先级 / 隐藏节点
cfg = rs.conf()
cfg.members[2].hidden = true       // 设为隐藏节点(不接读请求)
cfg.members[2].priority = 0        // 隐藏节点 priority 必须 0
cfg.members[2].votes = 1
rs.reconfig(cfg)

9. 容量规划

9.1 数据大小估算

// 数据库大小
db.stats()

// 集合大小(含索引)
db.users.stats()

// 只看数据大小(不含索引)
db.users.dataSize()      // 原始数据大小
db.users.storageSize()   // 磁盘实际占用(压缩后)
db.users.totalIndexSize() // 索引大小

// WiredTiger 压缩比通常 2-4 倍
// storageSize ≈ dataSize / 3

9.2 容量计算公式

磁盘需求 = 数据原始大小 / 压缩比(3) × 副本数(3) + 索引大小 × 副本数(3) + oplog(50GB) + 预留(20%)

示例:100GB 原始数据
- 压缩后数据:100/3 ≈ 33GB
- 索引约数据 10%:3.3GB
- 单节点:33 + 3.3 ≈ 36GB
- 3 副本:108GB
- oplog:50GB(每节点)
- 总计:(36 + 50) × 3 ≈ 258GB
- 加 20% 预留:约 310GB

9.3 内存规划

  • WiredTiger 缓存:物理内存 × 60%
  • 工作集(热数据)应能放入缓存
  • 经验:如果 bytes currently in cache 接近 max bytes configured,说明内存吃紧

9.4 连接数规划

最大连接数 = (可用内存 MB / 单连接内存) × 安全系数
单连接约占 1-2MB
8GB 内存 → maxConn ≈ 8000 × 0.5 = 4000(保守)

9.5 何时扩容信号

  • 缓存命中率持续 < 95%
  • 磁盘使用率 > 70%
  • 复制延迟频繁超 10 秒
  • 慢查询数量上升
  • 连接数接近上限

10. 版本升级与回滚

10.1 升级原则

  • 副本集滚动升级:逐个节点升级,保持多数派在线
  • 只能升级相邻大版本:5.0 → 6.0 → 7.0,不能跳级
  • 先升 Secondary,最后升 Primary
  • 升级前必须备份

10.2 副本集滚动升级步骤

# 假设从 6.0 升级到 7.0

# 0. 全量备份(第 5 节)

# 1. 设置兼容版本(在 Primary 执行)
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval '
  db.adminCommand({ setFeatureCompatibilityVersion: "6.0" })
'

# 2. 升级第一个 Secondary (mongo2)
docker stop mongo2
docker rm mongo2
# 修改 docker-compose 镜像版本为 mongo:7.0
docker compose up -d mongo2

# 等待 mongo2 恢复为 SECONDARY
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval 'rs.status()'

# 3. 升级第二个 Secondary (mongo3)
docker stop mongo3 && docker rm mongo3
docker compose up -d mongo3
# 等待恢复 SECONDARY

# 4. 手动切换 Primary 到已升级节点
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval 'rs.stepDown(60)'

# 5. 升级原 Primary (mongo1)
docker stop mongo1 && docker rm mongo1
docker compose up -d mongo1
# 等待恢复

# 6. 升级 featureCompatibilityVersion(全部升级后)
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval '
  db.adminCommand({ setFeatureCompatibilityVersion: "7.0" })
'

# 7. 验证
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval 'rs.status()'

10.3 回滚

# 回滚只能回到升级前的版本,且需在 setFeatureCompatibilityVersion 之前
# 一旦执行了 setFeatureCompatibilityVersion "7.0",无法降级数据格式

# 回滚步骤:
# 1. 停止 7.0 节点
# 2. 用备份恢复数据
# 3. 启动 6.0 版本

关键:setFeatureCompatibilityVersion 是不可逆操作!升级后观察一段时间再执行。


11. 故障排查手册

11.1 故障一:响应变慢

// Step 1: 看活跃操作
db.currentOp({ active: true, secs_running: { $gte: 1 } })

// Step 2: 杀掉慢操作
db.killOp("shard:12345")

// Step 3: 分析慢查询
db.system.profile.find().sort({ millis: -1 }).limit(5)

// Step 4: 查执行计划
db.coll.find({...}).explain("executionStats")
// 看 stage 是否 COLLSCAN(全表扫描)

// Step 5: 查锁等待
db.serverStatus().globalLock.currentQueue
// readers/writers > 0 说明有锁排队

// Step 6: 查内存
db.serverStatus().wiredTiger.cache
// "pages evicted" 高 = 内存不足

// Step 7: 查连接
db.serverStatus().connections
// current 接近 available 上限 = 连接耗尽

11.2 故障二:连接被拒

# Step 1: mongod 是否存活
docker ps | grep mongo
docker logs --tail 50 mongo1

# Step 2: 端口是否监听
netstat -tlnp | grep 27017

# Step 3: 系统连接限制
ulimit -n
cat /proc/$(pidof mongod)/limits | grep "open files"

# Step 4: MongoDB 连接上限
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval '
  db.serverStatus().connections
'

# Step 5: 网络/防火墙
firewall-cmd --list-ports
telnet <host> 27017

# Step 6: 认证
# 检查连接串 authSource 是否正确
# mongodb://user:pass@host/db?authSource=admin

11.3 故障三:复制延迟

// Step 1: 查看各节点状态
rs.status()
// 找出 stateStr 非 SECONDARY 或 lag 大的节点

// Step 2: 查看复制延迟详情
rs.printSecondaryReplicationInfo()

// Step 3: 查看延迟节点日志
// docker logs mongo2 | grep -i "replication\|error"

// Step 4: 查 Secondary 负载
// 是否 Secondary 承担了大量读请求或建索引
db.currentOp(true)

// Step 5: 查网络
ping -c 10 mongo2

// Step 6: 严重延迟时重新同步(见 8.4)

11.4 故障四:Primary 频繁切换

// Step 1: 查看选举历史
rs.status()

// Step 2: 查日志
// docker logs mongo1 | grep -i "election"

// 常见原因:
// - Primary 资源不足(OOM、CPU 满载)
// - 网络抖动(心跳超时)
// - 磁盘 IO 满载导致心跳响应慢
// - priority 配置不合理

// Step 3: 排查资源
docker stats mongo1
iostat -x 1
free -m

11.5 故障五:磁盘满

# Step 1: 确认磁盘
df -h

# Step 2: 找大文件
du -sh /data/mongo/node1/* | sort -rh

# Step 3: 紧急处理
# - 清理旧日志
docker exec mongo1 rm /var/log/mongodb/mongod.log.*
# - 清理 profile
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval '
  db.setProfilingLevel(0)
  db.system.profile.drop()
'
# - 压缩数据(compact,需停写)
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval '
  db.runCommand({ compact: "users" })
'

# Step 4: 长期方案:扩容磁盘 / 分片

11.6 故障六:数据损坏

# 症状: 启动报错 "WiredTiger error"

# Step 1: 停止 mongod
docker stop mongo1

# Step 2: 尝试修复(不一定成功)
docker run --rm -v /data/mongo/node1/db:/data/db mongo:7.0 \
  mongod --repair --dbpath /data/db

# Step 3: 修复失败则从备份恢复(第 5 节)
# 或从副本集其他节点重新同步(8.4)

12. 应急预案

12.1 Primary 宕机

影响: 写入中断 10-30 秒,自动选举新 Primary
处理:
1. 不用手动干预,等待自动选举(通常 < 30s)
2. 检查应用是否自动重连(连接串需含多个节点)
3. 排查宕机原因(OOM / 磁盘满 / 进程崩溃)
4. 修复原 Primary 后重启,会自动作为 Secondary 重新加入

12.2 多数派节点故障(脑裂/不可写)

影响: 副本集无法选举,完全不可写
处理:
1. 紧急启用单节点模式(仅灾难恢复用):
   docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval '
     db.adminCommand({ replSetForceResync: 1 })
   '
   # 或强制重配置为单节点
   cfg = { _id: "rs0", members: [{ _id: 0, host: "mongo1:27017" }] }
   db.adminCommand({ replSetReconfig: cfg, force: true })
2. 立即从备份恢复数据到新集群
3. 此操作有数据丢失风险,仅最后手段

12.3 误删数据

处理:
1. 立即停止应用写入(防止覆盖)
2. 从最近的备份恢复到新实例
3. 用 oplog 重放到误删前时间点(5.6 节)
4. 导出误删数据,写回生产库

12.4 安全事件(被勒索/未授权访问)

处理:
1. 立即断网(防火墙封禁 27017 对外)
2. 检查是否开启 auth(未开则数据已泄露)
3. 备份当前数据(留证)
4. 修改所有密码
5. 开启 auth + 绑定内网 IP
6. 评估泄露范围,按合规要求上报

13. 日常巡检清单

每日检查

# 1. 副本集状态
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval 'rs.status()' | grep stateStr

# 2. 复制延迟
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval 'rs.printSecondaryReplicationInfo()'

# 3. 磁盘空间
df -h | grep mongo

# 4. 容器状态
docker ps | grep mongo

# 5. 备份是否成功
ls -lh /data/mongo/backup/ | tail -5

# 6. 错误日志
docker logs --since 24h mongo1 2>&1 | grep -i "error\|fatal" | head -20

每周检查

// 1. 连接数趋势
db.serverStatus().connections

// 2. 缓存命中率
db.serverStatus().wiredTiger.cache
// 计算: (bytes read into cache) / (bytes read into cache + pages requested from cache)

// 3. 慢查询 TOP 10
db.system.profile.find().sort({ millis: -1 }).limit(10)

// 4. 索引使用情况
db.users.aggregate([{ $indexStats: {} }])

// 5. 数据增长
db.stats()

每月检查

# 1. 数据大小趋势
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval 'db.stats()' >> /data/mongo/logs/stats_$(date +%Y%m).log

# 2. 用户权限审计
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval '
  use admin
  db.getUsers()
' 

# 3. oplog 窗口是否足够
docker exec mongo1 mongosh -u root -p YourStrongPassword123 --eval 'rs.printReplicationInfo()'

# 4. 测试备份恢复(在测试环境)

# 5. 系统资源趋势分析(CPU/内存/IO 月度报告)

巡检脚本(可加入 crontab 每日执行)

#!/bin/bash
# /data/mongo/scripts/daily_check.sh
DATE=$(date +%Y%m%d_%H%M%S)
LOG="/data/mongo/logs/daily_check_${DATE}.log"
HOST="mongo1"
PASS="YourStrongPassword123"

mkdir -p /data/mongo/logs

echo "===== MongoDB 日常巡检 $DATE =====" > $LOG

echo -e "\n[1] 容器状态" >> $LOG
docker ps | grep mongo >> $LOG

echo -e "\n[2] 副本集状态" >> $LOG
docker exec $HOST mongosh -u root -p $PASS --quiet --eval '
  rs.status().members.forEach(m => {
    print(m.name + " | " + m.stateStr + " | lag: " + (m.optimeDate ? m.optimeDate : "N/A"))
  })
' >> $LOG

echo -e "\n[3] 连接数" >> $LOG
docker exec $HOST mongosh -u root -p $PASS --quiet --eval '
  let c = db.serverStatus().connections
  print("current: " + c.current + " / available: " + c.available)
' >> $LOG

echo -e "\n[4] 磁盘空间" >> $LOG
df -h | grep -E "mongo|Filesystem" >> $LOG

echo -e "\n[5] 最近错误日志" >> $LOG
docker logs --since 24h $HOST 2>&1 | grep -i "error\|fatal\|warning" | tail -10 >> $LOG

echo -e "\n[6] 备份文件" >> $LOG
ls -lh /data/mongo/backup/ | tail -3 >> $LOG

echo "巡检完成: $LOG"

附录:常用运维命令速查

// == 副本集 ==
rs.status()                        // 副本集状态
rs.isMaster()                      // 当前节点角色
rs.conf()                          // 副本集配置
rs.add("host:27017")               // 添加节点
rs.remove("host:27017")            // 移除节点
rs.stepDown(60)                    // Primary 让位
rs.printReplicationInfo()          // oplog 信息
rs.printSecondaryReplicationInfo() // 各节点延迟

// == 服务器状态 ==
db.serverStatus()                  // 完整状态
db.serverStatus().connections      // 连接数
db.serverStatus().opcounters       // 操作计数
db.serverStatus().wiredTiger.cache // 缓存
db.serverStatus().mem              // 内存

// == 操作与性能 ==
db.currentOp({active:true})        // 当前操作
db.killOp("opid")                  // 杀操作
db.setProfilingLevel(1,{slowms:100}) // 开慢查询
db.system.profile.find()           // 慢查询记录

// == 数据大小 ==
db.stats()                         // 库统计
db.coll.stats()                    // 集合统计
db.coll.dataSize()                 // 数据大小
db.coll.storageSize()              // 磁盘占用
db.coll.totalIndexSize()           // 索引大小

// == 索引 ==
db.coll.getIndexes()               // 查看索引
db.coll.createIndex({field:1})     // 建索引
db.coll.dropIndex("name")          // 删索引
db.coll.aggregate([{$indexStats:{}}]) // 索引使用统计

// == 用户 ==
use admin
db.getUsers()                      // 所有用户
db.createUser({...})               // 建用户
db.dropUser("name")                // 删用户
db.changeUserPassword("user","new")// 改密码

// == 维护 ==
db.fsyncLock()                     // 加锁(快照备份前)
db.fsyncUnlock()                   // 解锁
db.runCommand({compact:"coll"})    // 压缩集合
db.runCommand({repairDatabase:1})  // 修复(慎用)

运维学习路线

  1. 入门: 单机部署 → 熟悉 mongosh → 掌握 serverStatus 等诊断命令
  2. 副本集: 搭建 3 节点副本集 → 理解选举机制 → 练习故障转移
  3. 监控: 部署 Prometheus + Grafana → 理解五大监控维度 → 配置告警
  4. 备份: 实践 mongodump / 文件快照 → 演练恢复流程 → 搭建定时备份
  5. 调优: 理解 WiredTiger → 实践索引优化 → 慢查询治理
  6. 进阶: 分片集群 → 容量规划 → 版本升级演练
  7. 应急: 制定应急预案 → 定期故障演练 → 复盘总结

官方运维文档: https://www.mongodb.com/docs/manual/administration/
生产部署建议: https://www.mongodb.com/docs/manual/administration/production-notes/
```