
这是 MongoDB 监控系列文章的第七篇,前面几篇文章的链接如下:
按照前面系列文章,我们已经采集到 MongoDB 的监控数据了,并且通过 Grafana 和 Nightingale 的仪表盘看到了数据,这一节开始,我们来探索一下 MongoDB 的关键指标,对于未来配置告警规则、排查问题都有帮助。
核心要点
- MongoDB 监控不只是看单个指标是否异常,更重要的是把运行时间、操作量、延迟、连接数、游标、锁等待和查询效率放在同一个排障视角里理解。
- Grafana 仪表盘里的 panel 说明通常包含作者对指标的解释,阅读这些说明可以帮助我们判断指标类型、PromQL 写法和告警适用场景。
- Counter 类型指标通常需要用
rate或irate转成单位时间增量;Gauge 类型指标通常直接观察当前值或趋势。 - 对 MongoDB 告警来说,重启、连接耗尽、延迟升高、锁等待堆积、查询效率下降、断言事件持续升高,都是值得优先关注的信号。
通过 MongoDB Grafana 仪表盘查看 MongoDB 关键指标
一般仪表盘中每个图表的左上角,会有一个 i 图标,点击这个图标,可以看到这个图表的一些提示信息,这个信息可是非常重要,是制作仪表盘的那个人的经验总结。我们先看看 Grafana 那个仪表盘,看的时候注意看这个提示信息。
运行时间:mongodb_instance_uptime_seconds
这个指标是 MongoDB 实例的运行时间,这个指标是一个累加值,单位是秒,可以用来判断 MongoDB 实例的运行时间,如果这个值突然变小,说明 MongoDB 服务重启了。有人会创建一个告警规则:如果这个值小于 300,就报警,说明最近 5 分钟内发生过重启。当然了,这么粗暴的告警规则,在新实例刚刚启动的时候,也会报警。
从告警角度看,mongodb_instance_uptime_seconds 更适合用来识别“非预期重启”。如果实例刚发布、刚扩容或刚初始化,也会出现 uptime 较小的情况,因此这类告警最好结合维护窗口、实例创建时间或发布事件一起判断。
操作吞吐:qps
sum(irate(mongodb_op_counters_total{type!="command"}[5m]))
mongodb_op_counters_total 表示总的操作次数,显然是 counter 类型,即单调递增的,所以使用 irate 或 rate 求每秒操作次数,又因为 type 有多种取值,所以 sum 一下把各类操作求和,但是 type 排除了 command,不知道原因是啥,莫非是因为 command 是什么特殊操作?回头再研究。
QPS 可以帮助我们判断 MongoDB 当前是否有明显流量变化。排查问题时,QPS 本身不一定代表异常,但它能解释很多现象:延迟升高是否伴随请求量上升,连接数升高是否伴随业务流量上升,网络流量突增是否来自数据库操作变多。
操作延迟:latency
irate(mongodb_mongod_op_latencies_latency_total{type="command"}[5m]) / irate(mongodb_mongod_op_latencies_ops_total{type="command"}[5m])
mongodb_mongod_op_latencies_latency_total 是延迟总量,mongodb_mongod_op_latencies_ops_total 是操作总量,求 rate 之后再相除,就是每个操作的平均延迟了。具体细节还需要进一步研究。
平均延迟适合作为趋势观察指标。如果要做更严格的用户体验告警,还需要结合业务侧接口延迟或应用埋点,因为数据库命令平均延迟不一定等同于业务请求端到端耗时。
副本集角色:Current ReplSet State
这个图表有提示:
This shows the role of the selected service. Normally this should be one of PRIMARY, SECONDARY and ARBITER, but if the system is newly added it could show STARTUP2 during its initial sync.
看起来是 MongoDB 集群中某个实例的角色,一般是 PRIMARY、SECONDARY 和 ARBITER 三种,如果是新加入的实例,可能会显示 STARTUP2,这个提示很有用,可以帮助我们理解这个图表。但是我的显示的是 STARTUP,可能是因为我是一个 standalone 实例,不是集群。
在 Prometheus 生态里没法存储字符串,所以这里显示的内容显然是根据数字换算出来的,我们先看看这个图表对应的指标:
max by (instance) (mongodb_mongod_replset_my_state{})
核心就是 mongodb_mongod_replset_my_state 指标,这个指标是一个数字,根据这个数字,我们可以知道这个实例的角色。从图表上可以看到对应关系:

这个指标在副本集场景里很重要。监控时需要关注角色是否符合预期,例如 Primary 是否存在、Secondary 是否正常跟随、节点是否长时间处于 STARTUP2、RECOVERING 等非稳定状态。对于 standalone 实例,角色面板的解释要结合部署形态来看,不能简单套用副本集结论。
命令和复制相关操作:Command Operations
这个图表包含三个 promql:
irate(mongodb_op_counters_total{job="$job", instance="$instance", type!="command"}[5m])
irate(mongodb_mongod_op_counters_repl_total{job="$job", instance="$instance", type!~"(command|query|getmore)"}[5m])
irate(mongodb_mongod_metrics_ttl_deleted_documents_total{job="$job", instance="$instance"}[5m])
mongodb_op_counters_total 用于计算普通操作,mongodb_mongod_op_counters_repl_total 用于计算 repl 相关的操作,mongodb_mongod_metrics_ttl_deleted_documents_total 用于计算 TTL 删除的文档数。具体含义就需要研究 MongoDB 的文档和原理了,回头再说。
延迟明细:Latency detail
irate(mongodb_mongod_op_latencies_latency_total{job="$job", instance="$instance"}[5m]) / irate(mongodb_mongod_op_latencies_ops_total{job="$job", instance="$instance"}[5m]) > 0
这个 promql 和前面的 Latency 是一样的,只不过上面的是展示的当前值,下面这个展示的是趋势图,并且下面的会把不同的 type 的 command 都展示出来,这样可以看到不同操作的延迟情况。
连接数:Current Connections
mongodb_connections{job="$job", instance="$instance", state="current"}
对于数据库而言,连接数是一个非常重要的指标,这个图表展示了当前连接数,这个指标是一个 gauge 类型,即时的,不是累加值。
连接数适合和可用连接数、应用连接池配置、业务流量一起看。单纯“当前连接数高”不一定等于故障,但连接数持续升高、接近上限或伴随 rejected 连接时,通常需要尽快排查。
游标:Cursors
mongodb_mongod_metrics_cursor_open{job="$job", instance="$instance"}
这个图表展示了当前打开的游标数,这个指标是一个 gauge 类型,即时的,不是累加值。从图表的 legend 可以看出,这个指标有个 state 标签,用来区分不同状态的游标。
文档操作:Document Operations
irate(mongodb_mongod_metrics_document_total{job="$job", instance="$instance"}[5m])
表示文档操作的总数,这个指标是一个 counter 类型,即单调递增的,所以使用 irate 或 rate 求每秒操作次数。从 legend 可以看出,这个指标有个 state 标签,用来区分不同类型的文档操作。
锁等待队列:Queued Operations
这个 panel 有个提示:Operations queued due to a lock. 由于锁的缘故积压的操作数。
mongodb_mongod_global_lock_current_queue{job="$job", instance="$instance"}
没有使用 rate、irate 之类的,说明是一个 gauge 类型的指标,从 legend 看出这个指标有个 type 标签,用来区分不同类型的数据。
锁等待队列是排查性能问题时很有价值的信号。如果队列持续不为 0,说明操作在等待锁资源,需要结合慢查询、写入压力、索引设计和业务访问模式继续分析。
查询效率:Query Efficiency
Panel 提示:Ratio of Documents returned or Index entries scanned / full documents scanned。 返回的文档数或索引条目数与扫描的完整文档数的比率。
sum(irate(mongodb_mongod_metrics_document_total{job="$job", instance="$instance", state="returned"}[5m]))
/
sum(irate(mongodb_mongod_metrics_query_executor_total{job="$job", instance="$instance", state="scanned_objects"}[5m]))
另一个:
sum(irate(mongodb_mongod_metrics_query_executor_total{job="$job", instance="$instance", state="scanned"}[5m]))
/
sum(irate(mongodb_mongod_metrics_query_executor_total{job="$job", instance="$instance", state="scanned_objects"}[5m]))
如果扫描了很多,但是返回的很少,即上面的值较小说明效率低,反之效率高。具体还需要再研究。
查询效率可以帮助判断索引是否合适。若 scanned objects 很高而 returned 很低,通常意味着查询扫描了大量无效数据;这类问题不一定立即导致故障,但容易在流量上升时放大成延迟问题。
扫描和移动对象:Scanned and Moved Objects
这个 panel 有提示:This panel shows the number of objects (both data (scanned_objects) and index (scanned)) as well as the number of documents that were moved to a new location due to the size of the document growing. Moved documents only apply to the MMAPv1 storage engine。 此面板显示了由于文档大小增长而将对象(数据(scanned_objects)和索引(scanned))移动到新位置的数量,由于文档大小增长而移动的文档仅适用于 MMAPv1 存储引擎。
irate(mongodb_mongod_metrics_query_executor_total{job="$job", instance="$instance"}[5m])
另一个:
irate(mongodb_mongod_metrics_record_moves_total{job="$job", instance="$instance"}[5m])
这两个指标都是 counter 类型,即单调递增的,所以使用 irate 或 rate 求每秒操作次数。
getLastError 写入确认时间
这个 panel 有提示:Legacy driver operation: Number of, and Sum of time spent, per second executing getLastError commands to confirm write concern. 传统驱动程序操作:每秒执行 getLastError 命令以确认写入关注点的数量和时间总和。
irate(mongodb_mongod_metrics_get_last_error_wtime_total_milliseconds{job="$job", instance="$instance"}[5m])
这个指标明显是一个 counter 类型,单位是 milliseconds,求 rate 之后表示每秒中有多少 ms 是用于 getLastError 的。
断言事件:Assert Events
这个 panel 有提示:This panel shows the number of assert events per second on average over the given time period. In most cases assertions are trivial, but you would want to check your log files if this counter spikes or is consistently high. 此面板显示了给定时间段内每秒平均的断言事件数。 在大多数情况下,断言是微不足道的,但如果此计数器激增或持续很高,则应检查日志文件。
irate(mongodb_asserts_total{job="$job", instance="$instance"}[1m])
这个指标是一个 counter 类型,即单调递增的,所以使用 irate 或 rate 求每秒操作次数。
断言事件适合作为日志排查入口。如果该指标尖刺或持续偏高,需要回到 MongoDB 日志确认错误类型,不能只靠指标判断根因。
Page Faults
这个 panel 有提示:Unix or Window memory page faults. Not necessarily from mongodb. Unix 或 Windows 内存页面错误。 不一定来自 mongodb。
irate(mongodb_extra_info_page_faults_total{job="$job", instance="$instance"}[3m])
这个指标是一个 counter 类型,即单调递增的,所以使用 irate 或 rate 求每秒次数。
指标使用建议
| 监控问题 | 优先查看的指标 | 使用方式 |
|---|---|---|
| MongoDB 是否重启 | mongodb_instance_uptime_seconds |
观察是否突然变小,告警要排除新实例启动场景 |
| 请求量是否异常变化 | mongodb_op_counters_total |
用 rate 或 irate 计算每秒操作数 |
| 数据库是否变慢 | op latency、Latency detail | 与 QPS、锁等待、查询效率一起判断 |
| 是否有连接风险 | mongodb_connections |
观察 current 连接数趋势,并结合连接上限和 rejected 情况 |
| 是否存在锁等待 | mongodb_mongod_global_lock_current_queue |
Gauge 指标,持续不为 0 时要继续排查 |
| 查询是否低效 | document returned、query executor scanned | 关注扫描量与返回量的关系 |
总结
通过每个 panel 的研读,我们对 MongoDB 的监控知识又前进了一步。仪表盘不是只用来“看图”的,它把指标类型、PromQL 写法、数据库行为和告警场景连在一起。要想把 MongoDB 监控做好,后续还需要继续结合 MongoDB 文档、业务访问模式和真实故障案例来验证这些指标的阈值与解释方式。
FAQ
Q1:MongoDB 监控里哪些指标最适合先做告警? A:可以优先关注实例重启、连接风险、延迟升高、锁等待、断言事件、副本集角色异常等信号。这些指标更容易和可用性或排障动作关联。
Q2:为什么 Counter 指标要用 rate 或 irate?
A:Counter 是单调递增值,直接看原始值通常意义不大。用 rate 或 irate 可以把它转成单位时间内的变化量,例如每秒请求数、每秒断言事件数。
Q3:仪表盘上的指标能直接变成告警规则吗? A:不能机械照搬。仪表盘适合观察趋势,告警还要结合业务峰谷、维护窗口、实例角色、部署方式和历史基线,否则容易产生误报。
