介绍phpredis模块中,pconnect与connect连接的区别。
概述
1.connect
每次connect都会新建一个tcp连接;脚本运行结束之后自动断开连接。
2.pconnect
持久连接,标识id:
1.host + port + timeout
2.host + persistent_id
3.unix socket + timeout
每次pconnect会根据标识id在当前运行的httpd(指通过mpm模块创建出来的进程,web请求会被发送到这些进行进程处理,这些进程可处理多次web请求)或php-fpm进程中查找已存在的连接,如果存在则复用连接,否则新建连接;脚本运行结束之后不会自动断开连接,连接会保留在httpd或php-fpm进程中,除非进程关闭或连接空闲时间达到redis设置的timeout(timeout=0为永不超时)。
此特性在线程版本里是无效的,pconnect等同于connect。
测试准备
为了在测试时可以比较方便的观察连接,将apache的并发处理数调整为1。
httpd.conf
#启用httpd-mpm模块
Include conf/extra/httpd-mpm.conf
httpd-mpm.conf
<IfModule mpm_prefork_module>
StartServers 1
MinSpareServers 1
MaxSpareServers 1
MaxRequestWorkers 1
MaxConnectionsPerChild 0
</IfModule>
单次执行多连接测试
1.connect
$objRedis = new Redis();
$bln = $objRedis->connect('10.100.3.106', 6379, 3);
var_dump($objRedis->ping());
sleep(10);
$bln = $objRedis->connect('10.100.3.106', 6379, 3);
var_dump($objRedis->ping());
sleep(10);
$bln = $objRedis->connect('10.100.3.106', 6379, 3);
var_dump($objRedis->ping());
sleep(10);
redis客户端连接信息如下,可以发现3次连接的端口都是不同的,当重新连接时原来的连接会立即断开。



2.pconnect
1.相同的标识id
$objRedis = new Redis();
$bln = $objRedis->pconnect('10.100.3.106', 6379, 3, 'haha');
var_dump($objRedis->ping());
sleep(10);
$bln = $objRedis->pconnect('10.100.3.106', 6379, 3, 'haha');
var_dump($objRedis->ping());
sleep(10);
$bln = $objRedis->pconnect('10.100.3.106', 6379, 3, 'haha');
var_dump($objRedis->ping());
sleep(10);
redis客户端连接信息如下,可以发现3次连接的端口都是相同的,脚本执行过程中,age在一直增长,idle会在使用后重新从0开始计算。



2.不同的标识id
$objRedis = new Redis();
$bln = $objRedis->pconnect('10.100.3.106', 6379, 3, 'haha1');
var_dump($objRedis->ping());
sleep(10);
$bln = $objRedis->pconnect('10.100.3.106', 6379, 3, 'haha2');
var_dump($objRedis->ping());
sleep(10);
$bln = $objRedis->pconnect('10.100.3.106', 6379, 3, 'haha3');
var_dump($objRedis->ping());
sleep(10);
redis客户端连接信息如下,可以发现3次连接的端口都是不同的,每次连接时原来的连接不会立即断开,而是要等到timeout时间。



多次执行单连接测试
1.connect
$objRedis = new Redis();
$bln = $objRedis->connect('10.100.3.106', 6379, 3);
var_dump($objRedis->ping());
redis客户端连接信息如下,可以发现3次执行脚本端口都是不同的,每次都会重新创建连接。



2.pconnect
$objRedis = new Redis();
$bln = $objRedis->pconnect('10.100.3.106', 6379, 3, 'haha');
var_dump($objRedis->ping());
redis客户端连接信息如下,可以发现3次执行脚本端口都是相同的,每次执行后idle会更新为0,age(连接创建的时间)则会一直增长。



总结
1.connect
优点:
- 脚本执行结束会自动关闭连接,无需关心是否会持续占用连接
- 每次连接都是新的连接,连接之间不会互相影响
缺点:
- 在大量请求时会频繁的建立与关闭连接,占用资源,出现很多TIME_WAIT
适用场景:
2.pconnect
优点:
- 连接不会随着脚本的结束而关闭,会保留在httpd或php-fpm进程中,直到超时时间或进程关闭
- 每次连接时,会优先查找是否有可用连接,如果有则复用以前的连接,减少IO开销
缺点:
- 如果存在很多长连接,当超过redis的最大可用连接,会导致之后的连接连接不上
- 如果不同的web应用都使用长连接,且没有根据应用配置
标识id,会导致2个web应用共享连接,当出现如切换db时就会产生问题
适用场景:
- 高并发的http请求,可设置
timeout来及时关闭空闲的连接