http://blog.csdn.net/u013474436/article/details/53118475
现在不管是在缓存方面,还是NoSQL方面,Redis很火也很流行,但是使用方面的经验不是很多,包括Redis的一些优化配置,还有使用Redis的一些技巧和经验都没有一个官方的指导,所以在网上能搜索到很多相关的东西,但是发现不一定完全匹配自己遇到的一些问题,而且有的文章只是告诉你要这么做,但是没有深究到底是为什么?
最近碰到一个项目的优化,该项目其实逻辑很简单,大的结构就是处理用户的请求,然后读Redis,返回对应的数据。而问题的所在在于该项目有个特点,就是存在整点效应——平时访问量比较低,服务器压力不大,但是整点的时候并发能够达到平时的4-5倍,服务器完全抗不住。所以我们就慢慢梳理整个项目的架构,还有流程,想从中发现问题的所在。
为了先解决并发高服务器负载过高的问题,我们首先分析了…(话扯远了,背景就介绍到这里,呵呵。。)
首先先介绍下connect和pconnect的区别。
connect:脚本结束之后连接就释放了。
pconnect:脚本结束之后连接不释放,连接保持在php-fpm进程中。
为了验证这点,我们可以写个脚本测试一下。
其中服务器是nginx,php-fpm采用静态方式,因为动态方式下php-fpm的进程数量可能会变化,所以为了简单我们采用静态方式启动。
其中php-fpm的数量我们设置成5个。
下面的脚本测试使用connect的情况,我们让脚本连接到redis,然后休眠10s。
<?php
$app = new App ();
$app->get ( '/', function () {
$redis = new Redis ();
$redis->connect ( '127.0.0.1' );
sleep(10);
echo 'Hello World';
// $redis->close ();
} );
return $app;
然后我们运行5个请求:
curl http://localhost:8081/
1
这时候我们可以看下redis中的connect_clients:
$ redis-cli info | grep connected_clients
connected_clients:14
1
2
等脚本运行完毕之后我们再看一下connect_clients:
$ redis-cli info | grep connected_clients
connected_clients:9
1
2
之前建立的redis连接资源被释放了。
我们修改上面的代码,把connect改成pconnect:
<?php
$app = new App ();
$app->get ( '/', function () {
$redis = new Redis ();
$redis->pconnect ( '127.0.0.1' );
sleep(10);
echo 'Hello World';
// $redis->close ();
} );
return $app;
和上面同样的操作,发现脚本脚本运行结束后connected_clients还是14:
$ redis-cli info | grep connected_clients
connected_clients:14
1
2
这说明脚本运行结束后,redis连接资源并没有释放,而是由php-fpm进程保持(可以通过 kill php-fpm看到,当脚本停止运行后连接释放)
所以使用pconnect代替connect,可以减少频繁建立redis连接的消耗。
另外,使用pconnect还可以减少同一个进程(php-fpm)频繁建立连接的消耗,可以通过以下代码验证:
使用connect的情况:
<?php
$redis1 = new Redis();
$redis1->connect('127.0.0.1');
sleep(5);
$redis2 = new Redis();
$redis2->connect('127.0.0.1');
sleep(5);
//$redis->close();
//$redis2->close();
运行上述脚本,会发现connect_clients会增加2个。
使用pconnect的情况:
<?php
$redis1 = new Redis();
$redis1->pconnect('127.0.0.1');
sleep(5);
$redis2 = new Redis();
$redis2->pconnect('127.0.0.1');
sleep(5);
//$redis->close();
//$redis2->close();
而运行上述代码,connect_clients只会增加1个,这说明在一个进程中,pconnect是可以保持redis连接状态提供复用的。