Ubuntu 上定位与解决 MongoDB 性能瓶颈
一 快速定位瓶颈
- 使用 mongostat 观察关键指标:insert/query/update/delete、getmore、faults、qr/qw、ar/aw、net_in/net_out,当 faults 持续升高或 qr/qw 长期不为 0,多为内存不足或并发排队;await/r_await/w_await 偏高说明磁盘 I/O 压力大。示例:
mongostat --host 127.0.0.1 --discover。
- 使用 mongotop 查看集合级别的读写耗时,定位“热点集合/操作”。示例:
mongotop --host 127.0.0.1 1。
- 打开并分析慢查询日志:Ubuntu 默认日志路径为 /var/log/mongodb/mongod.log,默认记录超过 100 ms 的操作。可动态轮转日志:
use admin; db.runCommand({ logRotate: 1 }),并实时跟踪:tail -f /var/log/mongodb/mongod.log。
- 在 shell 中查看 serverStatus 与 wiredTiger.cache:
db.serverStatus().wiredTiger.cache 可核对缓存命中与使用情况。
以上工具能快速判断是 CPU、内存、磁盘 I/O、连接数 还是 查询/索引 导致的瓶颈。
二 硬件与操作系统层优化
- 存储与内存:优先使用 SSD,并确保足够内存;MongoDB 的 WiredTiger 以内存缓存数据和索引,命中率越高,磁盘压力越小。
- NUMA 与内存分配:在 NUMA 主机上,用
numactl -interleave=all 启动 mongod,减少跨 NUMA 访问延迟;必要时设置 vm.zone_reclaim_mode=0。
- 文件系统与挂载:使用 ext4/xfs,在
/etc/fstab 中将挂载选项改为 noatime(减少元数据写入)。
- I/O 调度与预读:根据磁盘类型选择合适的 I/O 调度器;适度降低预读,例如
blockdev --setra 16 /dev/sdX(范围可 16–256,视设备而定)。
- 虚拟化和共享存储:尽量避免 网络共享磁盘(NFS 等)带来的 I/O 争用,优先本地 SSD。
这些系统级优化能显著降低 I/O 等待与访问延迟。
三 配置层优化
- 调整 WiredTiger 缓存:在 /etc/mongod.conf 中设置
storage.wiredTiger.engineConfig.cacheSizeGB,建议预留 20%–30% 内存给操作系统与其他进程,避免换页。示例:
storage:
engine: wiredTiger
wiredTiger:
engineConfig:
cacheSizeGB: 8
修改后重启:sudo systemctl restart mongod,并用 db.serverStatus().wiredTiger.cache 验证。
- 连接与文件句柄:适度提升
net.maxIncomingConnections(如 10000–20000),并在 /etc/security/limits.conf 提高 nofile(如 65536),避免连接耗尽。
- 慢查询阈值:在
operationProfiling 中将 slowOpThresholdMs 设为 100–1000 ms(先大后小,逐步收敛问题)。
- 日志与轮转:确保
systemLog.path 指向 /var/log/mongodb/mongod.log,并配置合理的保留与轮转策略。
这些参数能直接缓解 连接瓶颈、缓存不足、慢查询堆积 等问题。
四 查询与索引优化
- 使用 explain(“executionStats”) 检查是否走索引、是否发生 COLLSCAN,并据此新增或调整索引。
- 为高频查询建立 复合索引,注意排序方向:例如
sort({country: -1, city: -1}) 能利用索引,而 sort({country: -1, city: 1}) 可能无法使用同一索引,需要建立匹配顺序的索引。
- 优化投影与分页:只返回必要字段(投影),避免大偏移分页(如
skip/limit 大数据量时改用 范围查询 + 索引)。
- 降低排序与聚合开销:尽量在索引上完成排序;聚合管道中尽早 $match/$project 减少处理数据量。
- 减少全表扫描与隐式转换:保证查询条件字段类型与索引一致,避免 `$or** 引发的多索引扫描(必要时改写为 $in 或复合索引)。
- 维护索引健康:删除 无用/重复 索引,必要时重建碎片化严重的索引(
db.collection.reIndex())。
这些手段通常能快速降低 延迟与 CPU 占用。
五 扩展与维护
- 读写分离与副本集:通过 副本集 将读请求分摊到 secondary,提升并发读能力。
- 水平扩展:当单实例容量或 I/O 达到上限时,引入 分片 将数据与负载分布到多台机器。
- 持续监控与告警:使用 mongostat/mongotop 与日志做日常巡检,必要时接入 Prometheus + Grafana 设置延迟/IO/连接数阈值告警。
- 版本与备份:升级到 稳定版本 获取性能修复;定期 mongodump/mongorestore 备份,保障可回滚。
这些措施帮助在业务增长时保持稳定的 吞吐与可用性。