WiredTiger缓存默认值不可直接使用,因其按宿主机内存计算,易在低配机或容器中导致OOM;必须根据实际可用内存(非宿主机总量)手动配置cacheSizeGB,预留系统开销后取50%~70%,并逐节点验证缓存命中与溢出情况。

WiredTiger缓存默认值为什么不能直接用
默认值在低配机器上容易吃光内存,比如 4GB RAM 的服务器,wiredTigerCacheSizePct 默认算出来是 1.5GB,但若同时跑 Java 应用、监控 agent 和系统进程,实际留给 MongoDB 的内存可能只剩 2GB 左右——WiredTiger 缓存一占 1.5GB,系统就开始频繁 swap,mongod 响应延迟飙升甚至被 OOM killer 干掉。
更隐蔽的问题是容器环境:Kubernetes 或 Docker 限制了容器内存(如 --memory=4g),但 WiredTiger 默认按宿主机总内存计算缓存上限,完全无视 cgroup 限制。这时候必须手动设值,否则 hostInfo 返回的 memSizeMB 是宿主机总量,不是容器可用量。
- 查真实可用内存:连接到 mongod 后执行
db.runCommand({hostInfo: 1}),看system.memSizeMB字段是否贴近你预期的容器或虚拟机内存 - 若明显偏大(比如容器设了 4GB,但返回 64GB),说明 WiredTiger 没感知到内存限制,必须显式配置
- 生产环境禁止依赖默认值,哪怕只部署三节点副本集,每个节点也要独立评估
怎么算出安全的 wiredTigerCacheSizePct 值
核心原则是:给操作系统和其它进程留够余量,再把剩余内存的 50%~70% 分给 WiredTiger。不是“越多越好”,而是“够用且不抢资源”。
- 先确认总可用内存(非宿主机,而是 mongod 进程实际能用的):Linux 下可看
/sys/fs/cgroup/memory/memory.limit_in_bytes(容器)或free -m(裸机) - 减去固定开销:预留至少 1.5GB 给 OS 缓存、日志缓冲、线程栈等;Java 应用共存时额外加 1GB
- 结果 × 0.6 就是推荐的缓存上限(单位 GB),再换算成百分比填入配置。例如:容器内存 8GB → 减 1.5GB OS 开销 = 6.5GB → × 0.6 = 3.9GB → 占 8GB 的 48.75%,即设
wiredTigerCacheSizePct: 48 - 注意下限:不能低于 0.256GB(256MB),否则 mongod 启动会报错
WiredTiger cache size must be between 0.256GB and 10000GB
配置方式选命令行还是 mongod.conf
必须用 mongod.conf,且只在此处设。命令行参数(如 --wiredTigerCacheSizeGB)仅适合临时调试,生产环境混用会导致配置漂移——比如 Ansible 模板写的是配置文件值,但 systemd service 文件里又带了命令行参数,优先级冲突后实际生效的值难以追溯。
YAML 配置示例(放在 storage.wiredTiger.engineConfig 下):
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 3.9
-
cacheSizeGB比wiredTigerCacheSizePct更直观,推荐优先用这个字段(MongoDB 3.4+ 支持) - 不要用
wiredTigerCacheSizePct算百分比再四舍五入——比如算出来 48.75%,填 49 会超限,填 48 又浪费,直接填小数更准 - 所有三节点副本集的每个成员,都要单独配置。主节点和副节点的负载特征不同(主节点写多、副节点读多),但缓存机制是统一管理的,所以值可以一致,但不能“复制粘贴完就不管”
改完缓存后必须验证的三件事
改配置不是改完重启就完事。WiredTiger 缓存行为直接影响数据页命中率和磁盘 IO,不验证等于没调。
- 连上节点执行
db.serverStatus().wiredTiger.cache,重点看bytes currently in the cache是否稳定在你设的值附近(允许 ±5% 浮动),如果长期只占 30%,说明数据集小或访问模式冷,可适当调低 - 观察
cache overflow pages read into cache:非零值代表缓存不够用,频繁从磁盘加载页,这时要优先扩容缓存或优化查询(比如避免全集合扫描) - 检查
db.stats()中dataSize与storageSize比值,若storageSize远大于dataSize(比如 3 倍以上),说明压缩率低,可能需要调整blockCompressor(默认 snappy,高压缩可换 zstd,但 CPU 开销上升)
三节点副本集里最容易被忽略的是:仲裁节点(arbiter)也走同一套缓存逻辑,但它不存数据,cacheSizeGB 设太高纯属浪费内存,建议仲裁节点设为 0.5GB 或直接用默认值——它只参与投票,不处理读写请求。











