MongoDB在写入密集型应用程序中表现异常糟糕

7
我正在运行一个写入密集型的MongoDB Web应用程序,但它的性能非常差。但我比较确定问题与我们的代码、设置和/或使用有关,而不是mongo本身。
我快要因绝望而砸开我的头,所以我想知道是否有人可以看一下我准备好的一些输出,看看是否有什么问题。
- db.stats() - fstab, mdadm 和 iostat -xm 2 - mongostat 这个代码并不太复杂(顺便说一下,它是用PHP编写的)。它基本上是许多的-find()和-update()操作。我确保对两个调用都使用了索引,并通过对查询进行解释(explain())来确认它们确实被使用。
我尝试了1个服务器(ec2 m2.2xlarge),4个服务器(2个副本集的2个分片)和9个服务器(3个副本集的3个分片),但是没有取得太大的成果。在好时候,我最多只能获得每秒1500次写入(插入+更新)。大部分时间,我很幸运能够达到100次插入/更新的总量,而且我总是有一个很大的“locked%”和很多排队的查询“qr | qw”。现在,我有一个正在运行并正在爬行的脚本。最糟糕的是,当我观察mongostat一段时间后,“res”中使用的RAM量约为服务器可用RAM的50%,并且有足够的RAM来适合所有集合的索引。没有理由为什么这不会像疯狂地输出数据。我必须已经重编码了应用程序2-3次,尝试找到更好的数据访问模式。我读了所有关于索引、更新、分片键等方面的文章。我放置mongo的所有服务器都使用了8个EBS磁盘RAID 10设置,并添加了一些性能调整(blockdev,noatime等)。
我知道问题出在我的端上,不是在责怪mongodb。我知道比我更大的公司正在使用它进行写入密集型应用,并且他们绝对喜欢它(例如foursquare)。同时,无论我做什么,我都无法理解我做错了什么以及为什么我会得到如此糟糕的表现。
附加信息:
- 所有服务器(客户端和服务器)都在运行Ubuntu 10.04 LTS和MongoDB 1.8.2。 - 所有服务器都在EC2 East并且在同一个区域内。 - 目前,我回到了1个m2.2xlarge服务器(4个核心,34.2 GB RAM),直到我能找出问题所在。
1个回答

11

首先问题是你的磁盘主要是读取而不是写入,这可以从iostat中得知。你的利用率超过了50%,但基本上都是读取。

如果看一下数据库统计信息,索引有35GB,数据有41GB,分配文件总共133GB。 133GB和mongostat中的mapped数字非常接近。所以您访问的数据总量约为120GB或大约是RAM的4倍。

通常,4x是一个完全合理的比例。然而,在你的情况下,你的索引超过了RAM。这往往是MongoDB性能的“拐点”。

如果你随机访问索引,那么大多数或全部索引都在内存中。这意味着您的大部分数据不在内存中,需要从磁盘“分页”加载。这可以从你正在接收的大量磁盘读取中看出来。

我知道你说你已经测试过分片了,你有这些测试的数据吗?数据是否正确地分布在三个shard之间?

分片应该可以缓解你的问题,因为它相当于“向DB添加更多的RAM”,但是您需要确认数据确实被均匀地分片并且正常运行,否则它无法解决您的问题。


2
值得一提的是,如果您的更新无法在原地进行(因为它们已经超出了分配的可用空间),那么它们需要从磁盘中读取到内存中进行修改,并写回到数据集的末尾。+1 - Bryan Migliorisi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接