mongos内存高主要源于连接线程栈和未释放游标,而非缓存;WiredTiger配置对其无效;需通过ps aux或/proc/PID/status查真实RSS;聚合必须设allowDiskUse:true并精简字段;驱动需合理配置连接池与游标超时。

mongos 内存高不是因为缓存,而是连接和游标在“吃”内存
mongos 本身不走 WiredTiger 引擎,wiredTigerCacheSizeGB 对它完全无效。它的内存上涨几乎全来自两块:每个客户端连接分配的线程栈(默认上限 1MB),以及长期未释放的游标元信息。一旦应用端建立大量长连接、或发起聚合后不消费完结果,mongos 就会持续 hold 住这些资源。
查 mongos 真实内存占用,别被 free -m 或 buff/cache 欺骗
Linux 的 free -m 显示的 buff/cache 是文件系统页缓存,跟 mongos 进程 RSS 无关。真正要看的是:
-
ps aux --sort=-%mem | head -n 10中mongos进程的%MEM列 -
cat /proc/$(pgrep mongos)/status | grep VmRSS得到的实际物理内存(KB) - 连上 mongos 执行
db.serverStatus().mem,看resident字段(注意:这个值在 mongos 上意义有限,仅作参考)
聚合查询没加 allowDiskUse: true 是 OOM 最快路径
mongos 是聚合协调者,$sort、$group、$lookup 等操作的中间结果全得在它内存里合并。默认无内存限制,几万条带大文本字段的文档一聚合,RSS 直接飙到数 GB。
- 所有含
$sort或$group的聚合,必须显式传{ allowDiskUse: true }(这是客户端选项,不是 pipeline 阶段) - 聚合开头就
$project排除大字段:{ content: 0, attachment_data: 0 },别让 mongos 白搬数据 - 启动 mongos 时指定
--tempPath /data/mongos-tmp,并确保该路径是真实磁盘(非tmpfs)、空间充足(至少预留预估聚合数据量 × 2) - 检查 mongos 日志是否有
Failed to create temp directory或No space left on device
连接池和游标配置不当,会让内存缓慢爬升
mongos 不管理游标超时,也不自动回收空闲连接 —— 它只忠实地维持你给它的每一个连接和游标。
- 驱动里必须设
minPoolSize和maxPoolSize,例如 Node.js 驱动推荐minPoolSize: 10, maxPoolSize: 50;设minPoolSize: 0会导致低峰期连接全销毁、高峰重建,引发瞬时内存毛刺 -
maxIdleTimeMS别设太长(如 30 分钟),建议 ≤60000(1 分钟),避免空闲连接长期占着线程槽位 - Python/PyMongo 必须显式关掉游标保活:
.no_cursor_timeout(False),或用.batch_size(50)控制每次拉取量 - Java 驱动注意
connectTimeoutMS,若前置了 LB,建议显式设为5000,避免卡在中间层不反馈
--tempPath 路径权限与磁盘类型,以及驱动层游标生命周期的完全失控 —— 这些都不在 mongos 日志里体现,但却是压垮它的最后一根稻草。


















