MongoDB 性能监控指标详解与实战经验
日常运维 MongoDB 时,总是会遇到性能问题。这篇文章整理了我在实际项目中用过的几个关键监控命令和指标,从 mongostat 到锁监控,分享一些踩坑经验和实用技巧。
前言
最近项目里的 MongoDB 又开始拖后腿了,查询慢、连接数爆满、偶尔还来个锁等待。
作为一线搬砖工,我发现很多时候性能问题其实有迹可循,关键是要知道看哪些指标、怎么看。今天整理一下我在日常运维中经常用到的几个 MongoDB 监控命令,希望能帮到同样被性能问题折磨的伙伴们。
几个常用的监控命令
mongostat - 实时状态一览
这个命令可以说是我的老朋友了,基本每次排查性能问题都会先跑一下:
mongostat --host localhost:27017
输出的指标挺多,我们重点关注几个:
- insert/query/update/delete:每秒的 CRUD 操作数,能直观看到负载分布
- dirty/used:WiredTiger 存储引擎特有的缓存指标,dirty 是脏数据比例,used 是缓存使用率
- qr|qw:读写队列长度,这个一高基本就是性能瓶颈的信号了
- ar|aw:活跃的读写客户端数量
- conn:当前连接数
我的经验是,qr|qw 经常大于 0 就要注意了,说明请求在排队等待;dirty 长期超过 20% 也不太正常。
mongotop - 看看哪张表最忙
mongotop 10 # 每10秒刷新一次
这个命令能告诉我们具体是哪个库、哪张表在消耗时间:
- ns:库表名(namespace)
- total:该表操作的总耗时
- read/write:读写操作分别的耗时
经常能通过这个命令发现某个集合成了性能瓶颈,然后针对性地去优化索引或者查询。
db.serverStatus() - 最全面的状态信息
这个命令返回的信息巨多,我一般重点看锁相关的部分:
db.serverStatus().locks
输出类似这样:
{
"Global" : {
"acquireCount" : {
"r" : NumberLong(1234), // 意向共享锁获取次数
"w" : NumberLong(567), // 意向排他锁获取次数
"R" : NumberLong(89), // 共享锁获取次数
"W" : NumberLong(12) // 排他锁获取次数
},
"acquireWaitCount" : {
"r" : NumberLong(10), // 获取锁时需要等待的次数
"w" : NumberLong(5)
},
"timeAcquiringMicros" : {
"r" : NumberLong(50000), // 等待锁的总时间(微秒)
"w" : NumberLong(20000)
}
}
}
实战中的经验总结
什么时候该紧张了?
通过这段时间的摸索,我总结了几个需要立马关注的信号:
- 队列长度持续大于 0:qr|qw 不是偶尔飙升,而是持续排队
- 锁等待频繁:acquireWaitCount 增长很快,说明锁竞争激烈
- 缓存命中率低:如果 used 很低但查询还是慢,可能是索引有问题
一个真实的踩坑案例
前几个月遇到过一次,mongostat 显示 qw(写队列)一直在 10+ 徘徊,写操作巨慢。
最开始以为是硬件问题,后来通过 mongotop 发现是某个日志表在疯狂写入,再配合 db.serverStatus() 看到 W(排他锁)的 acquireWaitCount 在飙升。
最终发现是业务代码里有个循环写入没加批量操作,改成 bulk insert 之后立马就好了。
所以这些监控指标不是看着玩的,关键时刻真能救命。
日常监控的小建议
我现在的习惯是:
- 定期跑 mongostat:了解系统的基本负载情况
- 性能问题时用 mongotop:快速定位是哪个集合的问题
- 深入分析靠 db.serverStatus():特别是锁相关的指标
当然,具体的阈值和告警策略还是要根据自己的业务场景来调整。我这里分享的主要是思路和经验。
小结
MongoDB 的性能监控其实不复杂,关键是要知道看什么、怎么看。
这几个命令基本能覆盖日常 80% 的性能问题排查需求。剩下的就是多实践、多踩坑,慢慢积累经验了。
最后提醒一句:db.serverStatus() 基本没有性能消耗,可以放心在生产环境使用。但 mongostat 和 mongotop 如果频率太高还是会有一定开销的,适度就好。
那就开始用起来吧~
