在执行慢速查询时,我们在 MongoDB PHP 驱动程序 (v1.3) 中遇到了一些奇怪的行为。当请求很慢时,驱动程序似乎会继续打开连接,我不完全理解为什么。或许你们在这里有一些建议。
以下是一些事实:
- 网站和数据库在单个 Ubuntu 13.04 服务器上运行
- 服务器是高端8核16GB RAM服务器
- MongoDB v2.2.4
- 网站运行 PHP 5.4
- Apache 2 作为 Web 服务器
- PHP Mongo 驱动 1.3.x (应该是最新的 1.3)
- 网站使用 Doctrine ODM
- 网站随时有大约 50 到 100 个并发用户
- ulimit 打开文件 (ulimit nofile) = 64000
每天一次,Memcache 记录过期并完成慢速查询。这导致 PHP 最多打开 800 个与 MongoDB 的连接(根据日志,通常我们有 10 个打开的连接)。我们的网站几乎完全是 Memcached,因此我们的数据库没有任何其他重大负载。800 个打开的连接使网站一开始有 30 秒的加载时间,然后抛出几种类型的 MongoExceptions(连接/套接字异常太多)。
这是一个带有 group by 的丑陋查询。明确地说,我们知道这个查询很慢而且很愚蠢,我们今天要删除这个查询。只是不清楚为什么它搞砸了整个网站。我们使用 Doctrine 作为抽象层,但根据日志,这是对 200,000 个文档数据库(每个文档 3 个字段:id/product/date)的实际查询:
{"group":true,"keys":{"product":1},"initial":{"count":0},"reduce":"function (obj, prev) { prev.count++; }","options":[],"db":"Orders","collection":"History"}
查询完成后,其结果将写入 Memcache 24 小时。所以所有新请求都从 Memcache 获取,而不是从 MongoDB 获取。但是,它仍然保持大约 800 个连接,问题并没有自行解决,并且网站在一段时间后不再响应。打开这 800 个连接大约需要 10 分钟。
感觉就像一个典型的比赛条件。查询只是感觉不够重,无法在此负载下实际导致此服务器上的竞争条件。我的意思是,感觉不应该。
好的,所以问题是:
- 为什么 PHP 总是打开这么多连接?
- 为什么 MongoDB 不能处理这个问题(这应该不是什么大问题,对吧?)
- 关于我们应该做什么的任何其他建议?
- 我应该在连接和查询上设置超时来解决这个问题还是别的什么?
我问这个的原因是因为我们的网站增长非常快,我们预计未来会有更多的流量和 MongoDB 负载。
提前非常感谢!