MongoDB容器化服务持续高CPU分析解决
一、先确认症状和根因
CPU 飙高的类型
- 持续 100%:可能是查询/写入本身负载太大,或索引缺失。
- 周期性尖刺:可能是 GC(WiredTiger 内存回收)、后台任务(如 TTL 索引清理、compact)。
- 容器内核态 CPU 高:可能是 IO wait、锁竞争、cgroup 限制导致频繁调度。
工具检查
mongostat、mongotop看热点集合、操作类型。db.currentOp()查看长时间运行的查询。explain("executionStats")分析慢查询。- 容器宿主机层面:
docker stats、htop -p <pid>、perf top。
二、查询与索引优化(最关键)
慢查询优化
- 打开
profilingLevel=1或2,收集慢查询日志。 - 使用
db.collection.find().explain()查看是否走了 COLLSCAN。 - 针对高频条件加合适索引,注意复合索引字段顺序。
- 打开
聚合管道优化
$match尽量前置,减少数据集。$project控制字段数量,避免不必要的字段进入内存处理。
避免大批量未分页查询
- 替换
skip/limit为 基于索引的 range 查询。 - 大量删除或更新时,分批次执行。
- 替换
三、存储引擎与配置优化
MongoDB 默认是 WiredTiger,CPU 消耗可能来自压缩/解压和内存管理。
压缩配置
- 默认集合数据:
block_compressor=zstd(CPU 消耗比 snappy 高)。 - 如果 CPU 紧张、磁盘空间宽裕,可以改成
snappy或none。
1
2
3
4storage:
wiredTiger:
collectionConfig:
blockCompressor: snappy- 默认集合数据:
连接池与并发
- 容器内应用是否创建了大量连接?MongoDB 的连接管理会吃 CPU。
- 建议使用连接池(如
maxPoolSize控制)。
内存参数
wiredTigerCacheSizeGB可手动限制,避免频繁 eviction 导致 CPU 高。
四、容器化部署层面优化
资源限制
cpu_quota和cpu_shares过小,MongoDB 被限制,导致频繁调度/抢占 CPU。- 建议:至少 4 核以上,避免单核瓶颈。
NUMA / Cgroups
- 如果是 K8s 部署,检查
cpu-manager-policy=static,绑定 CPU,避免迁移。 - NUMA 跨节点访问可能增加 CPU 消耗。
- 如果是 K8s 部署,检查
存储卷性能
- MongoDB 写多、读多,IOPS 不足时 CPU 会被卡在 IO wait。
- 确保卷类型:NVMe/SSD 优于 HDD;避免用 overlayfs(可用 direct-lvm)。
五、后台任务影响
- TTL 索引清理:大量过期文档会触发删除,占 CPU。
- Compact:手动运行时 CPU 会很高。
- Oplog:如果是副本集,检查复制延迟,落后节点可能推高 primary CPU。
六、优化思路总结
- 先监控定位:用
mongotop、db.currentOp()找出 CPU 热点集合/操作。 - 索引优化:缺索引或错误索引是第一大元凶。
- 存储参数调优:压缩算法、cache size、连接池。
- 容器侧优化:CPU/IO 资源限制合理化,优先考虑固定 CPU 亲和。
- 架构优化:分片集群 / 副本集读写分离,缓解单节点压力。