mongostat和mongotop无法反映副本集健康状态,真正有效的是mongodb_exporter+prometheus+grafana方案;需启用replicasetstatus采集器、直连primary、授予clustermonitor权限,并关注mongodb_replset_member_health等核心指标。

mongostat 和 mongotop 不能反映副本集节点健康状态——它们只看单个实例的瞬时操作流量,完全不感知 PRIMARY/SECONDARY 角色、心跳失败、同步延迟或 health: 0 这类关键信号。真正能落地监控健康状态的路径,是用 mongodb_exporter 暴露指标 + Prometheus 抓取 + Grafana 可视化,但必须注意 exporter 的连接方式和指标选取逻辑。
为什么 mongodb_exporter 默认不暴露 rs.status() 类指标
mongodb_exporter 默认只采集 serverStatus 和 dbStats 等基础指标,而副本集成员状态(如 members[n].stateStr、members[n].optimeDate、members[n].lastHeartbeat)需显式启用复制集模式:
- 启动时必须加 --collectors.enabled=replicasetstatus 参数,否则 mongodb_replset_member_state 等指标根本不会出现
- 它内部调用的是 replSetGetStatus 命令,但仅当连接目标是副本集成员(非 mongos 或 config server)且有足够权限时才成功
- 若用普通用户连接,需提前在 admin 数据库授予 clusterMonitor 角色,否则 exporter 日志会报 not authorized on admin to execute command { replSetGetStatus: 1 }如何正确配置 exporter 连接副本集并抓取成员指标
Exporter 必须直连某个副本集成员(推荐 PRIMARY),不能靠 DNS SRV 或随机 seed list 自动发现拓扑: - 连接字符串格式必须为mongodb://user:pass@host:port/?authSource=admin,不能省略 authSource
- 不要使用 mongodb+srv:// 协议——它会尝试连接所有节点,而 exporter 当前版本对多节点发现支持不稳定,易卡在第一个不可达节点上
- 若副本集跨网络分区,建议为每个关键节点单独部署一个 exporter 实例(监听不同端口),避免单点故障导致整组指标丢失
- 验证是否生效:访问 http://localhost:9216/metrics,搜索 mongodb_replset_member_state,应看到类似 mongodb_replset_member_state{member="node1:27017",set="rs0"} 1(1 = PRIMARY)或 2(2 = SECONDARY)
哪些 exporter 指标真正反映节点健康,哪些只是干扰项
重点关注以下几类指标,它们直接映射rs.status() 中的关键字段:
- mongodb_replset_member_health:值为 0 或 1,对应 members[n].health,是判断节点是否“存活”的第一道过滤器
- mongodb_replset_member_state:整数值,1=PRIMARY,2=SECONDARY,7=ARBITER,8=DOWN,10=RECOVERING——比字符串更易做 PromQL 判断
- mongodb_replset_member_optime_date:Unix 时间戳,单位秒,用于计算与 PRIMARY 的延迟:time() - mongodb_replset_member_optime_date,结果 > 30 秒即告警
- mongodb_replset_member_last_heartbeat:时间戳,若为空或远小于当前时间(如差 > 10 秒),说明心跳已断
- 警惕误用:mongodb_mongod_metrics_document_deleted_total 这类指标来自 oplog 应用计数,不是节点状态;mongodb_connections_current 是连接数,和复制健康无关
在 Prometheus 中写告警规则的实际要点
PromQL 表达式必须考虑副本集动态性,避免硬编码节点名: - 检测失联节点:mongodb_replset_member_health == 0,配合 absent(mongodb_replset_member_last_heartbeat) 排除初始化未完成场景
- 检测同步严重滞后:time() - mongodb_replset_member_optime_date > 60,但需加 and mongodb_replset_member_state == 2 限定只查 SECONDARY
- 检测意外降级(PRIMARY 变成 SECONDARY):mongodb_replset_member_state == 2 and on(set) group_left() mongodb_replset_member_state{state="1"} offset 5m ——过去 5 分钟还是 PRIMARY,现在却不是
- 所有规则都应加 for: 2m,防止瞬时抖动误报;标签中保留 set 和 member,方便告警精准定位到具体节点
真正难的不是采集,而是理解每个 exporter 指标背后对应的 rs.status() 字段含义。一旦把 mongodb_replset_member_state 和 members[n].stateStr、mongodb_replset_member_optime_date 和 members[n].optimeDate 映射清楚,后续所有告警和看板就都有了确定依据。











