【问题标题】:EC2 - MongoDB - PyMongo - Debugging Query LatencyEC2 - MongoDB - PyMongo - 调试查询延迟
【发布时间】:2013-03-04 09:18:06
【问题描述】:

我有 2 个 EC2 实例,一个作为 mongodb 服务器,另一个是 python Web 应用程序(相同的可用区)。 python服务器使用PyMongo连接到mongo服务器,一切正常。

问题是,当我在 python 中分析执行时间时,在某些调用(少于 5%)中,它甚至需要几秒钟才能返回。我能够缩小问题范围,并且时间延迟实际上是在对 mongo 服务器的 db 调用上。

我认为的两个原因是, 1. Mongo服务器速度慢/过载 2. 网络延迟

所以,我尝试将 mongo 服务器升级到快 4 倍的实例,但问题仍然存在(有些调用甚至需要 3 秒才能返回)我假设由于两台服务器都在 EC2 上,网络延迟应该不是问题......但可能是我错了。

如何确认问题是否真的是网络本身?如果是这样,解决它的最佳方法是什么?还有其他可能的原因吗?

感谢任何帮助...

谢谢,

UPATE:我获取的实体非常小(已编入索引),通常调用只需 0.01-0.02 秒即可完成。

更新:

按照“James Wahlin”的建议,我在我的 mongo 服务器上启用了分析并获得了一些有趣的日志,

3 月 15 日星期五 18:05:22 [conn88635] 查询 db.UserInfoShared 查询:{ $or: [ { _locked: { $exists: false } }, { _locked: { $lte: 1363370603.297361 } } ], _id: "750837091142" } nto return:1 nscanned:1 nreturned:1 reslen:47 2614ms

3 月 15 日星期五 18:05:22 [conn88635] 命令 db.$cmd 命令:{ findAndModify: "UserInfoShared", 字段: { _id: 1 }, upsert: true, 查询:{ $or: [ { _locked: { $exists: false } }, { _locked: { $lte: 1363370603.297361 } } ], _id: "750837091142" }, 更新: { $set: { _locked: 1363370623.297361 } }, new: true } ntoreturn:1 reslen:153 2614ms

您可以看到这两个调用需要 2 多秒才能完成。 _id 字段是唯一索引的,查找它不应该花费这么多时间。可能是我必须为此发布一个新问题,但是 mongodb GLOBAL LOCK 会是原因吗?

【问题讨论】:

  • 您是否在 mongod 进程中启用了慢速查询分析?这将告诉您时间是否在 MongoDB 中花费。有关详细信息,请参阅以下内容:docs.mongodb.org/manual/tutorial/manage-the-database-profiler
  • 问题是延迟随机发生,我需要将python进程与mongo查询时间相关联。是的,分析器记录了慢速查询,但很难将其与特定的 python 请求相关联。谢谢。
  • 您可以在查询中添加一个 id 以用于排队吗?

标签: mongodb amazon-ec2 pymongo


【解决方案1】:

@James Wahlin,非常感谢您帮助我。

事实证明,延迟的主要原因是 mongodb GLOBAL LOCK 本身。我们的锁定百分比平均为 5%,有时会达到 30-50% 的峰值,这会导致查询缓慢。

如果您遇到此问题,首先必须启用 mongodb MMS 服务 (mms.10gen.com),这将使您深入了解数据库服务器中到底发生了什么。

在我们的案例中,LOCK PERCENTAGE 非常高,原因有很多。你要做的第一件事就是阅读关于并发的 mongodb 文档, http://docs.mongodb.org/manual/faq/concurrency/

锁的原因可以是应用层、mongodb或硬件。

1) 我们的应用程序做了很多 updates 并且每次更新(超过 100 ops/sec)在 mongodb 中都包含一个 global lock。问题是当一个不在内存中的条目发生更新时,mongo 必须先将数据加载到内存中,然后更新(在内存中),整个过程发生在global lock 中。如果说整个事情需要 1 秒才能完成(0.75sec 从磁盘加载数据,0.25sec 在内存中更新),则整个其余的更新调用都将等待(整个1 sec)并且此类更新开始排队……你会发现应用服务器中的请求越来越慢。

解决方案(虽然听起来可能很傻)是在创建update 之前对相同的数据发送query。它的有效作用是将“加载数据到内存”(0.75 秒)部分移出global lock,这大大减少了您的lock percentage

2) 全局锁的另一个主要原因是mongodb的数据flush到磁盘。基本上每 60 秒(或更少)mongodb(或操作系统)将数据写入磁盘,并在此过程中保存 global lock。 (这有点解释了随机慢查询)。在您的 MMS 统计信息中,请查看 background flush avg 的图表...如果它很高,则意味着您必须获得更快的磁盘。

在我们的例子中,我们移动到EC2 中的一个新的EBS optimized 实例,并将我们配置的IOPS100 提高到500,这几乎将background flush avg 减半,服务器现在更快乐了.

【讨论】:

  • 嗨,吉姆,感谢您的精彩解释。你能告诉我们你每秒有多少读/升/写(平均或总数)吗?我只是想看看你的流量大小。非常感谢。
猜你喜欢
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-26
  • 2014-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多