MongoDB容器化服务持续高CPU分析解决

一、先确认症状和根因

  1. CPU 飙高的类型

    • 持续 100%:可能是查询/写入本身负载太大,或索引缺失
    • 周期性尖刺:可能是 GC(WiredTiger 内存回收)、后台任务(如 TTL 索引清理、compact)。
    • 容器内核态 CPU 高:可能是 IO wait、锁竞争、cgroup 限制导致频繁调度。
  2. 工具检查

    • mongostatmongotop 看热点集合、操作类型。
    • db.currentOp() 查看长时间运行的查询。
    • explain("executionStats") 分析慢查询。
    • 容器宿主机层面:docker statshtop -p <pid>perf top

二、查询与索引优化(最关键)

  1. 慢查询优化

    • 打开 profilingLevel=12,收集慢查询日志。
    • 使用 db.collection.find().explain() 查看是否走了 COLLSCAN。
    • 针对高频条件加合适索引,注意复合索引字段顺序。
  2. 聚合管道优化

    • $match 尽量前置,减少数据集。
    • $project 控制字段数量,避免不必要的字段进入内存处理。
  3. 避免大批量未分页查询

    • 替换 skip/limit基于索引的 range 查询
    • 大量删除或更新时,分批次执行。

三、存储引擎与配置优化

MongoDB 默认是 WiredTiger,CPU 消耗可能来自压缩/解压和内存管理。

  1. 压缩配置

    • 默认集合数据:block_compressor=zstd(CPU 消耗比 snappy 高)。
    • 如果 CPU 紧张、磁盘空间宽裕,可以改成 snappynone
    1
    2
    3
    4
    storage:
    wiredTiger:
    collectionConfig:
    blockCompressor: snappy
  2. 连接池与并发

    • 容器内应用是否创建了大量连接?MongoDB 的连接管理会吃 CPU。
    • 建议使用连接池(如 maxPoolSize 控制)。
  3. 内存参数

    • wiredTigerCacheSizeGB 可手动限制,避免频繁 eviction 导致 CPU 高。

四、容器化部署层面优化

  1. 资源限制

    • cpu_quotacpu_shares 过小,MongoDB 被限制,导致频繁调度/抢占 CPU。
    • 建议:至少 4 核以上,避免单核瓶颈。
  2. NUMA / Cgroups

    • 如果是 K8s 部署,检查 cpu-manager-policy=static,绑定 CPU,避免迁移。
    • NUMA 跨节点访问可能增加 CPU 消耗。
  3. 存储卷性能

    • MongoDB 写多、读多,IOPS 不足时 CPU 会被卡在 IO wait。
    • 确保卷类型:NVMe/SSD 优于 HDD;避免用 overlayfs(可用 direct-lvm)。

五、后台任务影响

  • TTL 索引清理:大量过期文档会触发删除,占 CPU。
  • Compact:手动运行时 CPU 会很高。
  • Oplog:如果是副本集,检查复制延迟,落后节点可能推高 primary CPU。

六、优化思路总结

  1. 先监控定位:用 mongotopdb.currentOp() 找出 CPU 热点集合/操作。
  2. 索引优化:缺索引或错误索引是第一大元凶。
  3. 存储参数调优:压缩算法、cache size、连接池。
  4. 容器侧优化:CPU/IO 资源限制合理化,优先考虑固定 CPU 亲和。
  5. 架构优化:分片集群 / 副本集读写分离,缓解单节点压力。