我们有一个 mongodb 实例运行在 amazon ec2 大型 (7.5GB) ubuntu 实例上(我们的 node.js 服务器运行在同一台机器上)。最近流量增加了很多,我们开始看到 mongodb 的一些不稳定行为。当前状态:
我们在使用分析器时注意到了一些速度很慢的查询:
query mydb.user 1327ms Wed Aug 01 2012 14:01:39
query:{ "_id" : ObjectId("500f45486562e7053d070363") } idhack responseLength:178 client:127.0.0.1 user:
用户表中的条目很少,但表中大约有 5000 万个条目。这种情况每隔一两分钟就会发生一次,随后会出现一系列慢查询。当我们使用 命令行执行慢查询时explain()
,不会报告任何异常。
mongostat
告诉我:
insert query update delete getmore command flushes mapped vsize res faults locked % idx miss % qr|qw ar|aw netIn netOut conn set repl time
138 804 9 0 96 36 0 60.2g 121g 3.42g 2 1.8 0 0|0 1|0 93k 479k 19 fgset M 14:15:59
94 755 4 0 71 35 0 60.2g 121g 3.41g 0 1.5 0 0|0 1|0 78k 344k 19 fgset M 14:16:00
93 17 4 0 75 27 0 60.2g 121g 3.41g 0 1.2 0 0|0 1|0 24k 31k 19 fgset M 14:16:01
87 86 6 0 73 33 0 60.2g 121g 3.41g 0 0.9 0 0|0 1|0 31k 260k 19 fgset M 14:16:02
101 531 3 0 62 19 0 60.2g 121g 3.41g 0 1 0 0|0 1|0 60k 1m 19 fgset M 14:16:03
92 713 2 0 66 24 0 60.2g 121g 3.41g 1 0.9 0 0|0 0|0 72k 1m 17 fgset M 14:16:04
163 91 6 0 93 46 0 60.2g 121g 3.41g 2 9.5 0 0|0 1|0 44k 256k 17 fgset M 14:16:05
108 62 6 0 79 38 0 60.2g 121g 3.41g 4 1.2 0 0|0 1|0 32k 122k 17 fgset M 14:16:06
137 23 6 0 81 32 0 60.2g 121g 3.41g 0 2.3 0 0|0 0|0 32k 67k 17 fgset M 14:16:07
pidstat -r -p <pid> 5
告诉我:
02:18:01 PM 1700 647.00 0.80 126778144 3578036 46.80 mongod
02:18:06 PM 1700 1092.00 1.20 126778144 3586364 46.91 mongod
02:18:11 PM 1700 689.60 0.20 126778144 3578912 46.81 mongod
02:18:16 PM 1700 740.80 1.20 126778144 3577652 46.79 mongod
02:18:21 PM 1700 618.60 0.20 126778144 3578100 46.80 mongod
02:18:26 PM 1700 246.00 1.00 126778144 3577392 46.79 mongod
请注意,我们的数据库卷是单个 ext4 卷,而不是 raid 集受到推崇的。
我不确定下一步该怎么做才能充分理解问题并实施修复。任何意见都值得赞赏。
答案1
我必须更仔细地观察一段时间内的趋势才能确定(彩信会有所帮助),但您可能遇到一个问题,即您已达到该实例上 MongoDB 的最大驻留内存 - 页面错误不是那么高,但我确实看到驻留内存略有下降。如果其他地方(来自另一个进程)存在内存压力,您可能会从 MongoDB 中逐出页面和/或不得不比应有的更频繁地将页面发送到磁盘(EBS 上的页面发送到磁盘非常慢)。
有几件事你可以做,以使你的 RAM 使用更加高效:
- 删除不必要的索引 - 如果使用它们,它们只会占用宝贵的 RAM - 适合删除的是单个索引,它们是其他地方的复合索引的最左边元素。这实际上取决于您的使用情况和架构,因此我只能提供一般性建议。
- 调整 EBS 卷上的预读向下- 这与您通常阅读到的关于调整 EBS 卷的内容相反,但当您的访问配置文件是随机的而不是顺序的时,预读设置得太高实际上会拖累内存使用。
要查看卷的预读设置,请运行此命令(需要 root/sudo 权限):
sudo blockdev --report
输出将列出如下内容:
RO RA SSZ BSZ StartSec Size Device
rw 256 512 4096 0 10737418240 /dev/xvda1
我们想在这里调整的是 RA 列(256,我相信这是亚马逊的默认设置)。您可以通过运行以下命令来执行此操作:
blockdev --setra <value> <device name>
对于上面的例子,我首先将值减半:
blockdev --setra 128 /dev/xvda1
我将更详细地介绍应该将此值设置多低以及其背后的原因这个答案如果您想了解更多信息。请注意,更改需要重新启动 mongod 进程才能生效。
完成上述两件事后,您可能能够从该 xlarge 实例的 RAM 中榨取更多性能。如果不能,或者内存压力来自其他地方,而效率不够高,那么是时候获得更多 RAM 了。
将 EBS 存储升级到 RAID 卷(如您所述)或使用新的预配置 IOPS 和 EBS 优化实例(或者如果你有足够的钱,可以使用 SSD 集群计算节点)将有助于解决操作中“缓慢”的部分(从磁盘分页),但没有什么能比得上内存操作的好处——即使磁盘子系统有所改进,它们仍然快一个数量级。