我们mongod
在虚拟机上运行了一个实例,它似乎没有使用所有可用内存。它的页面错误比平时多得多,系统性能最近明显下降。
更具体地说,如果我htop
mongod
,我会看到:
- 虚拟资源:3471G
- 分辨率:11.8G
该虚拟机有约 60 GB 的内存,目前约有 4.6GB 被“使用”,其余部分在缓冲区或缓存中。
我的理解是,这mongod
mmap
是数据库文件。(这就是为什么它VIRT
如此巨大。)但是,我们不清楚为什么这个RES
数字不接近 60 GB:由于mongod
需要磁盘上的数据,这些数据应该被带入 RSS 进程,不是吗?Mongo 报告说它正在发生页面错误,因此人们会认为 RSS 会随着时间的推移而增长;我们的 RSS 保持稳定。
这台机器上没有运行其他重要程序。(这是数据库服务器。)什么程序占用了剩余的缓冲区和缓存,具体来说,为什么RES
大小mongod
没有扩展到填满可用的 RAM?
答案1
这可能是一个漫长而复杂的过程,但让我先说一下,这只是一个起点。我(以及和我一起工作的许多其他人)已经设法接近最大常驻内存使用率。这个最大值具体是多少将因系统而异,并且有很多变量在起作用,但我通常会争取达到 60-80%,任何更高的值都是额外的奖励。
接下来要做的是阅读一些资料。关于这个主题的文章很多,通常是从另一个角度(更好的内存效率、在 RAM 已满时装入更多内存等)撰写的。例如:
- 将更多数据装入 RAM 问答(具体来说我自己关于预读的回答)
- 更多关于预读设置
- 之前类似的问题MongoDB 虚拟内存使用情况
- 还有几款不错的常问问题 页面在相关的 MongoDB 文档中
了解了以上所有情况后,你希望对如何调整系统以充分利用可用内存有一个大致的了解(通常,但并非总是,降低预读并确保NUMA 已禁用成功),并且能够看到内存压力可能来自何处。接下来要理解的部分有点棘手,涉及 MongoDB 日志的工作原理,以及它如何与内核跟踪各个进程的内存使用情况进行交互。
MongoDB Jira 的一个长问题中详细介绍了这一点 -服务器-9415。我们在调查该问题时发现,在执行读写混合操作时,日志的行为可能会(并非总是如此,但可以重现)大幅减少 MongoDB 进程报告的驻留内存。此机制已由克里斯蒂娜·乔多罗Jira 问题中还有更多详细信息。
那么,这一切意味着什么?
这意味着报告和解释驻留内存统计信息非常复杂,尤其是在同时执行写入操作的系统上,尤其是当该系统在进程之外存在内存压力时mongod
。一般来说,我建议采用以下方法:
- 读入(触碰或使用大型查询/解释进行手动预热)大量已知的、应该装入内存的数据
- 在该数据集上运行一些查询、聚合等,并验证页面错误是否最少
- 如果页面错误率较低,则数据适合内存,您有报告问题。您可以用更大的数据集重复测试,直到找到实际限制。
- 如果页面错误率很高,那么数据已经被逐出,没有完全加载等等,你需要调查一些事情(预读,内存压力,确保NUMA被禁用等等)
我一般建议跑步MMS 监控(免费)在测试时,它可以让您跟踪内存统计信息以及一段时间内的非映射内存、页面错误等,以及mongostat
(分辨率不到一分钟)就能清楚了解正在发生的事情。