phpredis provides function of persistent connnection with pconnect function of phpredis extension. We can hold a persistent connection during request process, hence reduce number of TIME_WAIT connections on php-fpm server side. This article introduces pconnect with an experiment using tcpdump to capture network packages between redis and php-fpm.
- start redis server with specified config file
redis-server /opt/homebrew/etc/redis.conf
- capture packages with tcpdump, please note that it's need to quit other clients to avoid noise package from other connections' keepalive acks
sudo tcpdump -i lo0 port 6379
- write code with phpredis and run it
<?php
try{
$redis = new Redis();
$redis->pconnect('127.0.0.1', 6379, 1);
$redis->set('test', 1);
$ret = $redis->get('test');
var_dump($ret);
echo "working...\n";
sleep(30);
$ret = $redis->get('test');
var_dump($ret);
} catch(Exception $e) {
var_dump($e);
}
php test.php
- firstly, let's turn off tcp-keepalive in redis.conf
# Close the connection after a client is idle for N seconds (0 to disable)
timeout 10
tcp-keepalive 0
As can be seen from above picture, after about 10 seconds, the redis-server closes the connection with 4 handshakes,
16:39:27.075901 IP localhost.6379 > localhost.59362: Flags [F.], seq 13, ack 54, win 6378, options [nop,nop,TS val 2198101393 ecr 1351616343], length 0
16:39:27.076022 IP localhost.59362 > localhost.6379: Flags [.], ack 14, win 6379, options [nop,nop,TS val 1351627220 ecr 2198101393], length 0
16:39:46.205701 IP localhost.59362 > localhost.6379: Flags [F.], seq 54, ack 14, win 6379, options [nop,nop,TS val 1351646349 ecr 2198101393], length 0
16:39:46.205850 IP localhost.6379 > localhost.59362: Flags [.], ack 55, win 6378, options [nop,nop,TS val 2198120522 ecr 1351646349], length 0
before the last get operation after sleep 30 seconds, phpredis reconnects redis-server,
16:39:46.206462 IP localhost.59428 > localhost.6379: Flags [S], seq 2930100989, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 4164075404 ecr 0,sackOK,eol], length 0
16:39:46.241196 IP localhost.6379 > localhost.59428: Flags [S.], seq 1624890732, ack 2930100990, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 3580418301 ecr 4164075404,sackOK,eol], length 0
16:39:46.241247 IP localhost.59428 > localhost.6379: Flags [.], ack 1, win 6379, options [nop,nop,TS val 4164075440 ecr 3580418301], length 0
Higher version of phpredis has implemented broken connection reconnect mechanism to fix the closed connection by redis-server.
- secondly, turn on tcp-keepalive in redis.conf, set it to 10
timeout 0
tcp-keepalive 3
as can be seen from above picture, redis-server sends tcp-keepalive packages to phpredis after 3 seconds idle, the connection stays until end without being closed by redis, because the 50115 port of phpredis socket is the same from beginning.
- thirdly, what if timeout and tcp-keepalive are both non-zero value,
timeout 10
tcp-keepalive 3
this time after about 3 seconds, the redis-server sent keepalive packages to phpredis,
17:19:31.809098 IP localhost.6379 > localhost.50741: Flags [.], ack 54, win 6378, length 0
17:19:31.809238 IP localhost.50741 > localhost.6379: Flags [.], ack 13, win 6379, options [nop,nop,TS val 2792756661 ecr 2917953310], length 0
17:19:34.810586 IP localhost.6379 > localhost.50741: Flags [.], ack 54, win 6378, length 0
17:19:34.810661 IP localhost.50741 > localhost.6379: Flags [.], ack 13, win 6379, options [nop,nop,TS val 2792759662 ecr 2917953310], length 0
17:19:37.811504 IP localhost.6379 > localhost.50741: Flags [.], ack 54, win 6378, length 0
17:19:37.811553 IP localhost.50741 > localhost.6379: Flags [.], ack 13, win 6379, options [nop,nop,TS val 2792762663 ecr 2917953310], length 0
after about 10 seconds, redis-server sent FIN packages to phpredis, at the same time, tcp-keepalive packages is sent as expected,
17:19:39.064945 IP localhost.6379 > localhost.50741: Flags [F.], seq 13, ack 54, win 6378, options [nop,nop,TS val 2917963567 ecr 2792762663], length 0
17:19:39.065056 IP localhost.50741 > localhost.6379: Flags [.], ack 14, win 6379, options [nop,nop,TS val 2792763917 ecr 2917963567], length 0
17:19:42.067199 IP localhost.6379 > localhost.50741: Flags [.], ack 54, win 6378, length 0
17:19:42.067286 IP localhost.50741 > localhost.6379: Flags [.], ack 14, win 6379, options [nop,nop,TS val 2792766919 ecr 2917963567], length 0
17:19:45.068725 IP localhost.6379 > localhost.50741: Flags [.], ack 54, win 6378, length 0
17:19:45.068924 IP localhost.50741 > localhost.6379: Flags [.], ack 14, win 6379, options [nop,nop,TS val 2792769920 ecr 2917963567], length 0
17:19:48.069275 IP localhost.6379 > localhost.50741: Flags [.], ack 54, win 6378, length 0
17:19:48.069412 IP localhost.50741 > localhost.6379: Flags [.], ack 14, win 6379, options [nop,nop,TS val 2792772921 ecr 2917963567], length 0
17:19:51.069801 IP localhost.6379 > localhost.50741: Flags [.], ack 54, win 6378, length 0
17:19:51.069866 IP localhost.50741 > localhost.6379: Flags [.], ack 14, win 6379, options [nop,nop,TS val 2792775922 ecr 2917963567], length 0
17:19:54.070723 IP localhost.6379 > localhost.50741: Flags [.], ack 54, win 6378, length 0
17:19:54.070757 IP localhost.50741 > localhost.6379: Flags [.], ack 14, win 6379, options [nop,nop,TS val 2792778923 ecr 2917963567], length 0
17:19:57.072783 IP localhost.6379 > localhost.50741: Flags [.], ack 54, win 6378, length 0
17:19:57.072864 IP localhost.50741 > localhost.6379: Flags [.], ack 14, win 6379, options [nop,nop,TS val 2792781925 ecr 2917963567], length 0
17:19:58.812707 IP localhost.50741 > localhost.6379: Flags [F.], seq 54, ack 14, win 6379, options [nop,nop,TS val 2792783664 ecr 2917963567], length 0
17:19:58.812853 IP localhost.6379 > localhost.50741: Flags [.], ack 55, win 6378, options [nop,nop,TS val 2917983314 ecr 2792783664], length 0
then new connection has been established with new port,
17:19:58.813183 IP localhost.50819 > localhost.6379: Flags [S], seq 3973721175, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 3671806542 ecr 0,sackOK,eol], length 0
17:19:58.844556 IP localhost.6379 > localhost.50819: Flags [S.], seq 2989861952, ack 3973721176, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 3634094131 ecr 3671806542,sackOK,eol], length 0
17:19:58.844625 IP localhost.50819 > localhost.6379: Flags [.], ack 1, win 6379, options [nop,nop,TS val 3671806574 ecr 3634094131], length 0
17:19:58.844646 IP localhost.6379 > localhost.50819: Flags [.], ack 1, win 6379, options [nop,nop,TS val 3634094146 ecr 3671806574], length 0