【问题标题】:Mongo suffering from a huge number of faultsMongo 遭受大量故障
【发布时间】:2012-09-12 18:35:04
【问题描述】:

我在我的 mongostat 输出中看到了一个巨大的(~200++)故障/秒数,尽管锁定百分比非常低:

我的 Mongo 服务器在亚马逊云上的 m1.large 实例上运行,因此它们每个都有 7.5GB 的 RAM ::

root:~# free -tm
             total       used       free     shared    buffers     cached
Mem:          7700       7654         45          0          0       6848

显然,我没有足够的内存来满足所有 cahin mongo 想要做的事情(顺便说一句,由于磁盘 IO,这会导致 CPU 使用率很高)。

我发现 this document 表明在我的场景中(高故障,低锁定 %),我需要“横向扩展读取”和“更多磁盘 IOPS”。

我正在寻求有关如何最好地实现这一目标的建议。也就是说,我的 node.js 应用程序执行了很多不同的潜在查询,我不确定瓶颈发生在哪里。当然,我试过了

db.setProfilingLevel(1);

但是,这对我没有多大帮助,因为输出的统计信息只是显示我的查询速度很慢,但我很难将这些信息转换为导致页面错误的查询...

如您所见,这导致我的 PRIMARY mongo 服务器上的 CPU 等待时间很长(几乎 100%),尽管 2x SECONDARY 服务器不受影响...

以下是 Mongo 文档对页面错误的评价:

页面错误表示 MongoDB 需要不在物理内存中的数据,并且必须从虚拟内存中读取数据的次数。要检查页面错误,请参阅 serverStatus 命令中的 extra_info.page_faults 值。此数据仅适用于 Linux 系统。

单独,页面错误很小并且很快完成;然而,总的来说,大量的页面错误通常表明 MongoDB 从磁盘读取了过多的数据,并且可以表明许多潜在的原因和建议。在许多情况下,MongoDB 的读锁会在页面错误后“让出”以允许其他进程读取并避免在等待下一页读入内存时阻塞。这种方法提高了并发性,在大容量系统中,这也提高了整体吞吐量。

如果可能,增加 MongoDB 可访问的 RAM 量可能有助于减少页面错误的数量。如果这不可能,您可能需要考虑部署一个分片集群和/或在您的部署中添加一个或多个分片以在 mongod 实例之间分配负载。

所以,我尝试了推荐的命令,这非常无用:

PRIMARY> db.serverStatus().extra_info
{
    "note" : "fields vary by platform",
    "heap_usage_bytes" : 36265008,
    "page_faults" : 4536924
}

当然,我可以增加服务器大小(更多 RAM),但这很昂贵,而且似乎有点矫枉过正。我应该实现分片,但我实际上不确定哪些集合需要分片!因此,我需要一种方法来隔离故障发生的位置(哪些特定命令导致故障)。

感谢您的帮助。

【问题讨论】:

  • 我知道这是一个老问题,但有几件事跳出来了。设置db.setProfilingLevel(1) 后,您需要接受这些查询并在它们上运行explain()。这些查询很可能没有使用索引并进行完整的集合扫描。您的辅助设备空闲是另一个令人担忧的原因,这取决于您的应用程序设置slaveOk=true 可以通过将一些负载放在辅助设备上来提供帮助。不过,我会先确保您的索引正常,否则您只是将痛苦传播给辅助服务器。

标签: node.js mongodb


【解决方案1】:

我们真的不知道您的数据/索引是什么样的。

仍然是 MongoDB 优化的重要规则:
确保您的索引适合 RAM。 http://www.mongodb.org/display/DOCS/Indexing+Advice+and+FAQ#IndexingAdviceandFAQ-MakesureyourindexescanfitinRAM.

考虑到您的文档越小,您的密钥/文档比率就越高,您的 RAM/磁盘大小比率就需要越高。

如果您可以稍微调整架构以将一些数据集中在一起,并减少所需的键数量,那可能会有所帮助。

【讨论】:

  • 似乎我错过了“每个查询一个索引”的部分。我也非常热衷于在架构周围使用索引,因为我没有意识到“必须适合 RAM”的约束。关于索引最佳实践的快速问题:当执行一个也使用 sort() 或 limit() 的查询时,我应该对这些字段进行索引吗?当我有搜索多个条件的查询时怎么样(例如,{'age': 30, 'name': y},有什么好的方法来决定应该为 2 列(两者?)中的哪一列建立索引?跨度>
  • 还有——在执行 db.XX.dropIndexes() 之后,我需要做些什么来恢复资源/停止我的 mongo 服务器上的页面错误吗?我删除了所有索引并以更保守的方式重新索引,但还没有看到任何改进。
  • 至于你的第一个问题。一般很难回答这些问题。这些是我们不断提出的问题,也是我们对模式设计所做的权衡。对于复合索引,如果您要搜索字段 A、A、B 或 A、B、C,那么您可以在 [A,B,C] 上创建复合索引。如果你然后搜索 B 或 C,它不会帮助你。 mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys
  • 所以...我确定这是解决方案,因为我最近添加了索引,所以我经历并在所有表上做了一个 dropIndexes(),但我的内存使用率几乎保持在 100% (根据 free -tm 命令)并且 CPU 没有下降……废话。 FWIW,我的 totalIndexSize(整个数据库)是 600MB,比我正在消耗的 7.5 GB RAM 小得多....
  • @ZaneClaes 您是否正在针对未编入索引的属性运行查询。因此需要进行全面扫描,因此您会看到很多故障?如果您搜索特定的 _id 会怎样? (如果您认为这不是正确的解决方案,请取消选中我的解决方案。)
猜你喜欢
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多