怎样监控MongoDB副本集各节点的健康状态?

作者:袖梨 2026-07-13
最准、最轻量的副本集健康判断依据是 mongodb_replset_member_health 指标,值为 0 即表示节点失联或不可用;该指标需通过启用 replicasetstatus 收集器并直连 PRIMARY 节点获取,配合 optimeDate 和 lastHeartbeat 可精准识别同步延迟与真实故障。

直接看 mongodb_replset_member_health 指标,值为 0 就代表节点失联或不可用——这是最准、最轻量的健康判断依据,比轮询 rs.status() 更适合告警和可视化。

为什么不能靠 mongostat/mongotop 判断副本集健康

mongostatmongotop 只反映单实例的实时操作吞吐,完全不感知副本集拓扑变化。它们看不到 health: 0、心跳超时、stateStr: "RECOVERING" 这类关键信号,也拿不到 lastHeartbeatoptimeDate 延迟数据。

常见错误现象:

  • 监控面板显示“QPS 正常”,但 SECONDARY 已断连 5 分钟,health 早已是 0
  • mongotop 看到某个节点“没流量”,误判为闲置,实际是它已降级为 ARBITER 或被踢出副本集

mongodb_exporter 必须启用 replicasetstatus 才能暴露健康指标

默认启动的 mongodb_exporter 不采集副本集成员状态,mongodb_replset_member_health 根本不会出现在 /metrics 中。

  • 启动时必须显式加参数:--collectors.enabled=replicasetstatus
  • 连接字符串不能用 mongodb+srv:// 协议——它会尝试连所有 seed 节点,一旦某个节点不可达,exporter 就卡住,指标全丢
  • 连接目标必须是副本集成员(推荐直连 PRIMARY),且用户需在 admin 库拥有 clusterMonitor 角色,否则日志报错:not authorized on admin to execute command { replSetGetStatus: 1 }
  • 验证是否生效:访问 http://localhost:9216/metrics,搜索 mongodb_replset_member_health,应看到类似 mongodb_replset_member_health{member="node1:27017",set="rs0"} 1

真正有用的健康指标就这几个,别被其他字段带偏

重点关注以下三项,它们直接对应 rs.status().members[n] 的核心字段:

  • mongodb_replset_member_health:0 或 1,是节点存活的第一道过滤器,告警阈值设为 0 即可
  • mongodb_replset_member_state:整数,1=PRIMARY,2=SECONDARY,7=ARBITER,8=DOWN —— 注意不是所有状态都等于“故障”,比如 STARTUP2 是正常初始化阶段
  • mongodb_replset_member_optime_date:配合 mongodb_replset_member_last_heartbeat 算延迟,若差值 > 30s,说明同步滞后,可能影响读一致性

别盯着 uptimelastAppliedWallTime 做健康判断——前者只表示进程运行时长,后者只是时间戳,不反映网络或复制链路是否通畅。

应用侧轮询 rs.status() 的实操要点

如果不用 Prometheus,而是写脚本或应用逻辑主动探测,db.runCommand({ rsStatus: 1 }) 是唯一可靠方式。

  • 命令必须发给 admin 数据库,不是任意 db;shell 里的 rs.status() 是封装函数,driver 里得用原生命令
  • 连接目标只能是副本集成员(不能连 mongos 或 config server),且建议固定连 PRIMARY,避免因节点角色切换导致命令失败
  • 重点解析字段:members[n].healthmembers[n].stateStrmembers[n].lastHeartbeat,忽略 myState(那是当前执行命令的节点状态,不是全局)
  • 轮询间隔建议 ≥10s;太频繁会加重 PRIMARY 负担,尤其当副本集节点多于 5 个时

复杂点在于:同一个节点可能短时间内反复在 RECOVERINGSECONDARY 之间跳变,这不是 bug,而是同步追赶过程中的正常震荡——健康判断要结合 healthoptimeDate 综合看,不能只认 stateStr 字符串。

相关文章

精彩推荐