判断副本集节点是否还活着,最直接、最可靠的指标是哪个?mongodb_replset_member_health。这个值一旦变成 0,就意味着节点失联或不可用——它比反复去轮询 rs.status() 要轻量得多,更适合作为告警和可视化的依据。

先厘清一个核心判断:mongodb_replset_member_health 值为 0 时,节点一定出了问题。但这个指标不会凭空出现,它需要你启用 replicasetstatus 收集器,并且直连 PRIMARY 节点才能获取。配合 optimeDate 和 lastHeartbeat,你就可以精准地区分到底是同步延迟,还是真的发生了故障。
为什么不能靠 mongostat/mongotop 判断副本集健康
mongostat 和 mongotop 这两个工具,本质上只反映单实例的实时操作吞吐量,完全不感知副本集拓扑的变动。它们看不到 health: 0、心跳超时、stateStr: "RECOVERING" 这类关键信号,也拿不到 lastHeartbeat 或 optimeDate 的延迟数据。
很多人都踩过这个坑:
- 监控面板上 QPS 看起来很正常,但某个 SECONDARY 已经断连好几分钟了,
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 }。 - 验证是否生效很简单:访问
https://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,说明同步滞后,可能影响读一致性。
千万别盯着 uptime 或 lastAppliedWallTime 来做健康判断——前者只说明进程还在跑,后者只是个时间戳,它们都反映不了网络或者复制链路是否真的通畅。
应用侧轮询 rs.status() 的实操要点
如果你不用 Prometheus,而是想写脚本或应用逻辑来主动探测,db.runCommand({ rsStatus: 1 }) 是唯一可靠的方式。
- 命令必须发给
admin数据库,不能随便选一个 db。shell 里的rs.status()是封装函数,driver 里得用原生命令。 - 连接目标只能是副本集成员,不能连
mongos或 config server。建议固定连 PRIMARY,避免因节点角色切换导致命令失败。 - 重点解析的字段是:
members[n].health、members[n].stateStr、members[n].lastHeartbeat。忽略myState,那只是当前执行命令的节点状态,不是全局信息。 - 轮询间隔建议 ≥10s。太频繁会加重 PRIMARY 的负担,尤其是副本集节点多于 5 个的时候。
还有一个复杂点:同一个节点可能短时间内反复在 RECOVERING 和 SECONDARY 之间跳变。这不是 bug,而是同步追赶过程中的正常震荡。所以健康判断得结合 health 和 optimeDate 综合来看,不能只认 stateStr 这个字符串。
