众所周知,PHP 的运行办法很难实现真正的连接池,不过通过本地的 Unix Domain Socket,我们可以绕开连接池,实现曲线救国,详细先容大家可以参考我以前写的旧文:史上最LOW的PHP连接池办理方案,在那篇文章里,我借助 Nginx 的 Stream 模块,实现了一个 Redis 代理,通过它来实现连接池功能,然后 PHP 通过本地的 Unix Domain Socket 来连接 Redis 代理,从而达到连接池的效果,不过在本文里,我不再自己编写 Redis 代理,而是直策应用 Twemproxy,让我们看看效果如何。
为了让 PHP 能够通过本地的 Unix Domain Socket 来连接 Redis 代理,PHP 和 Redis 代理必须安装在同一台做事器上,后端真正的 Redis 做事器常日不会和 PHP 在同一台做事器上,本文利用 127.0.0.1 是出于方便的考虑,假设你已经安装好了,让我们看看配置文件 /etc/redis.yml:
instance: listen: /var/run/nutcracker.sock redis: true redis_auth: ... preconnect: true servers: - 127.0.0.1:6379:1
让我们把做事运行起来,So easy:

shell> /path/to/nutcracker -c /etc/redis.yml
下面让我们压测看看性能怎么样,测试脚本 test.php 如下:
<?php$redis = new Redis;if (empty($_GET['twemproxy'])) { $redis->connect('127.0.0.1', 6379);} else { $redis->connect('/var/run/nutcracker.sock');}$redis->auth('...');$redis->set('foo', 'bar');echo $redis->get('foo');?>
通过 ab 仿照一个高并发的场景,压测看看性能有没有提升:
shell> ab -k -n 10000 -c 100 \"大众http://path/test.php?twemproxy=0\公众shell> ab -k -n 10000 -c 100 \"大众http://path/test.php?twemproxy=1\"大众
一开始,结果让人非常沮丧,利用 Twemproxy,没有带来任何性能上的提升。这是为什么呢?原来是由于 Twemproxy 是单线程的,缺省情形下只能利用一个 CPU,这个问题好办理,我们只要按 CPU 个数启动多个进程(假设有 4 个 CPU)即可。
首先,创建多个配置文件 /etc/redis[1-4].yml:
instance: listen: /var/run/nutcracker[1-4].sock redis: true redis_auth: ... preconnect: true servers: - 127.0.0.1:6379:1
然后,启动多个 Twemproxy 进程:
shell> /path/to/nutcracker -c /etc/redis1.yml -m 512 -s 11111 -dshell> /path/to/nutcracker -c /etc/redis2.yml -m 512 -s 22222 -dshell> /path/to/nutcracker -c /etc/redis3.yml -m 512 -s 33333 -dshell> /path/to/nutcracker -c /etc/redis4.yml -m 512 -s 44444 -d
相应的,测试脚本 test.php 也要做出适当的调度:
<?php$redis->connect('/var/run/nutcracker' . rand(1, 4) . '.sock');?>
再实行压测,结果创造利用 Twemproxy 后,性能整整提升了 100%!
如果你在压测过程中通过 top 命令不雅观察 CPU 情形的时候,会创造所有 CPU 都被吃满了,基本上没有 idle,此外,如果你在压测过程中通过 MONITOR 不雅观察 Redis 实行的命令,你会不雅观察到 Pipelining 征象,还会不雅观察到 AUTH 被省略了,这些都是性能提升的缘故原由。