为什么mongod没有使用所有可用的RAM?

我们有一个在虚拟机上运行的mongod实例,它似乎没有使用所有可用的内存。 这是一个比平常更严重的页面错误,系统的性能已经显着降低。

更具体地说,如果我知道,我会看到:

  • VIRT:3471G
  • RES:11.8G

虚拟机有大约60GB的内存,目前,〜4.6GB是“使用”,其余的是在缓冲区或caching

我的理解是, mongod mmap的数据库文件。 (这就是为什么VIRT是巨大的。)但是,我们不清楚RES为什么不接近60 GB:因为mongod需要closures磁盘的数据,这个数据应该被带入进程的RSS,不是? Mongo报告说这是页面错误,所以人们会认为RSS会随着时间而增长; 我们正在稳定。

这台机器上没有其他重要的东西在运行。 (这是数据库服务器。)什么是消耗其余的缓冲区和caching,特别是, 为什么mongodRES大小不扩大,以填补可用的RAM?

这可能是一个漫长的过程,但我首先要说这是一个起点。 我(和其他许多我一起工作过的)设法更接近最大常驻内存使用量。 到底什么样的最大值会随着系统的不同而变化,并且有很多变数,但是我通常会拍摄60-80%,更高的是奖金。

接下来要做的是读一些东西。 关于这个话题已经有了很多的文章,往往从另外一个angular度来看(更好的内存效率,当内存满的时候更多的进入内存等)。 例如:

  • 将更多的数据 填充 到RAM问答 (特别是我自己的回答关于预读 )
  • 有关Readahead设置的更多信息
  • 类似的前一个关于MongoDB虚拟内存使用的问题
  • 在MongoDB Docs中也有几个不错的FAQ 页面

所有这一切,你希望有一个体面的想法,关于如何调整你的系统,以充分利用可用的内存(通常,但不是总是,敲开readahead,并确保NUMA被禁用成功),是能够看到内存压力可能来自哪里。 下一个要理解的是有点棘手,涉及到MongoDB日志的工作方式,以及如何与内核如何跟踪单个进程的内存使用情况进行交互。

作为冗长的MongoDB Jira问题 – SERVER-9415的一部分详细介绍了这一点。 我们在调查这个问题时发现,他们在进行混合读写操作时的行为可能(并不总是,但却是可重复的)大大减less了MongoDB进程所报告的驻留内存。 Kristina Chodorow在这里详细描述了这个机制,Jira也有更多的细节。

那么,这是什么意思?

这意味着驻地记忆统计的报告和解释是复杂的,特别是在一个也在写作的系统上,特别是如果这个系统在mongod过程之外有内存压力。 一般来说,我推荐以下方法:

  • 用大的查询/解释读入( 用手触摸或手动预热)一大堆已知数量的数据应该放入内存中
  • 在该数据集上运行一些查询,聚合等,并validation页面错误是最小的
  • 如果页面错误是低的,那么数据正在装入内存,你有一个报告问题。 您可以使用更大的数据集重复testing,直到find您的实际限制。
  • 如果页面错误高,那么数据已被驱逐,没有完全加载等,你有什么要调查(预读,内存压力,确保NUMA被禁用等)

我通常build议在testing时运行MMS Monitoring (免费),因为这样可以跟踪内存统计信息以及随时间变化的非映射内存,页面错误等,以及mongostat (分1分钟分辨率)到底是怎么回事。