phpredis 是 PHP 开发 Redis 的封装,已经被广泛使用

The phpredis extension provides an API for communicating with the Redis key-value store.

It is released under the PHP License, version 3.01. This code has been developed and maintained by Owlient from November 2009 to March 2011.

 

phpredis 官网https://github.com/phpredis/phpredis

 

现在不管是在缓存方面,还是NoSQL方面,Redis很火也很流行,但是使用方面的经验不是很多,包括Redis的一些优化配置,还有使用Redis的一些技巧和经验都没有一个官方的指导,所以在网上能搜索到很多相关的东西,但是发现不一定完全匹配自己遇到的一些问题,而且有的文章只是告诉你要这么做,但是没有深究到底是为什么?

最近碰到一个项目的优化,该项目其实逻辑很简单,大的结构就是处理用户的请求,然后读Redis,返回对应的数据。而问题的所在在于该项目有个特点,就是存在整点效应——平时访问量比较低,服务器压力不大,但是整点的时候并发能够达到平时的4-5倍,服务器完全抗不住。所以我们就慢慢梳理整个项目的架构,还有流程,想从中发现问题的所在。

为了先解决并发高服务器负载过高的问题,我们首先分析了…(话扯远了,背景就介绍到这里,呵呵。。)

首先先介绍下connectpconnect的区别。 

connect:脚本结束之后连接就释放了。 

pconnect:脚本结束之后连接不释放,连接保持在php-fpm进程中。 

为了验证这点,我们可以写个脚本测试一下。 

其中服务器是nginxphp-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/

 

这时候我们可以看下redis中的connect_clients:

$ redis-cli info | grep connected_clients 
connected_clients:14

 

等脚本运行完毕之后我们再看一下connect_clients:

$ redis-cli info | grep connected_clients
connected_clients:9

 

之前建立的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

 

这说明脚本运行结束后,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连接状态提供复用的

 

 

参考推荐

PHP redis pconnect 长连接详解

PHP 高并发下请求 Redis 异常处理