Tag Archives: Mongo

PHP中执行Mongo的一个性能问题

最近正好在使用mongodb,在完成基础功能的时候,我习惯性的会对其性能进行一些测试,首先在mongo 2.6.4下进行测试,php版本会5.6。测试工具我使用的wrt,这是一个非常好用的压力测试工具,而且可以配合lua脚本,测试和聚合。

在Mongo 2.6.4下测试情况

由于业务的需要,我用500个并发+1分钟请求来进行了测试,主要针对读取,插入,更新已经调用执行js脚本。

1. mongo数据读取操作,结果是1320 reqs/sec。

2. mongo数据插入操作,结果是1240 reqs/sec。

3. mongo数据更新操作,结果是1250 reqs/sec。

以上三个结果,我还算能接受,但是接下来的测试,让我彻底惊到了。

由于业务上的需求,我在设计整个构架的时候,是考虑把一部分逻辑放在mongo中调用js直接执行的。测试脚本是

function getGameInfo(gameid) {
   if (gameid == undefined) {
       return false;
   }

   game = db.games.findOne({ gameid : gameid });

   if (game) {
      return game.toArray();
   }

   return false;
}

然后在php中执行,php的脚本为

$client = new MongoClient("mongodb://localhost:27017");
$db = $client->selectDB("test");
$code = "function getGameInfo(gameid) {
   if (gameid == undefined) {
       return false;
   }
   game = db.games.findOne({ gameid : gameid });
   if (game) {
      return game.toArray();
   }
   return false;
}";

$db->execute($code, array(10));
$client->close();

测试下来的结果只有35reqs/sec,而且mongo还报了连接数过多。首先mongodb的链接,在php中默认就是长链接,也就是说链接数过多,因为前面的数据执行了没有断开链接。但是我明明关闭链接了。

我Google了一下,在mongo中select是non-block,insert和update是collection级锁,而运行js脚本是全局锁,同时在mongo2.6.4下js是spidermonkey。主要原因找到了,因为全局锁,就必须等待前面一个脚本运行完成返回结果才行。同时现在Mongo已经升级到了3.0,它的JS引擎也从spidermonkey变成了V8,但同时在3.0,execute/eval函数了已经deprecated。

在Mongo 3.0.0下测试情况

MongoDB已经正式发布了3.0,根据官方的测试提高接近4倍的性能,我以1000个并发+1分钟请求进行测试,其结果确实让人满意不少。

1. mongo数据读取操作,结果是2320 reqs/sec。

2. mongo数据插入操作,结果是1840 reqs/sec。

3. mongo数据更新操作,结果是1950 reqs/sec。