predis与phpRedis是php连接redis最常用的两个包。在工作项目中,由于十分依赖redis,因此比较predis与phpRedis两者之间的性能差异。
写在前面
- 测试所用代码地址-github
- 测试环境
1.redis: Redis server v=2.9.11
2.php: PHP 7.1.29 (cli) (需安装 PHPRedis 扩展)
3.机器信息:Mac i5 8G内存
单机测试
分别顺序执行5W次redis写命令,比较他们的时间(ms)。
虽有一定差别,但差别不大。
次数 | predis | phpRedis |
---|---|---|
5w | 3000 | 2999 |
5w | 3000 | 3000 |
10w | 6000 | 6000 |
10w | 5001 | 5999 |
50w | 34999 | 33001 |
50w | 32000 | 28999 |
并发测试
写API,读写一定量key,统计时间。并使用ab并发测试,比较两者区别。
总次数 | 并发数 | 读写数 | predis | phpRedis | 备注 |
---|---|---|---|---|---|
1000 | 100 | 2000 | 333968 | 309012 | redis变卡,可能有大量等待 |
5000 | 100 | 200 | 203008 | 201993 | redis变卡,可能有大量等待 |
5000 | 50 | 200 | 234967 | 177043 | 差距变大 |
5000 | 100 | 20 | 25002 | 14007 | 差距继续扩大,猜测phpredis 在建立连接可能更快 |
5000 | 100 | 20 | 20996 | 13003 | 同上 |
5000 | 100 | 2 | 7000 | 4999 | |
5000 | 100 | 2 | 10002 | 4999 | |
5000 | 100 | 1 | 10996 | 2001 | 基本确定是建立连接 耗时差距 |
5000 | 100 | 1 | 7999 | 2001 |
// 随机建立连接
$t = rand(0,1);
if ($t == 0) {
$this->testRedis(new phpRedisConn());
}else{
$this->testRedis(new PredisConn());
}
// 测试代码
private function testRedis(conn $conn)
{
$mode = $conn->getMode();
$startTime = Comm::getMillisecond();
Comm::PrintEcho("string 测试开始..." . "当前时间:" . $startTime . " 测试方式:" . $mode);
for ($i = 0; $i < self::NUM; $i++)
{
$conn->set($conn->getMode(), $i);
}
$endTime = Comm::getMillisecond();
$useTime = $endTime - $startTime;
$conn->incrby("useTime_" . $mode, $useTime);
Comm::PrintEcho("string 测试结束..." . "消耗时间:" . $useTime . " 测试方式:" . $mode);
}
复用连接
phpRedis较predis还有一个有点,就是phpredis实现了pconnect()。pconnect在redis结束后,不会销毁redis连接,直到空闲超时自动断开。pconnect是依赖与php-fpm进程的,进程不死,connect就会存在。
/*
* $host redis IP $port redis 端口
* $timeout 默认无限(进程销毁或者redis超时断开)
* $persistent_id 连接标示 新的标示 建立新连接
*/
public function pconnect( $host, $port = 6379, $timeout = 0.0, $persistent_id = null )
// 加入新的连接方式
$t = rand(0,2);
if ($t == 0) {
$this->testRedis(new phpRedisConn());
}elseif ($t == 1)
{
$this->testRedis(new PredisConn());
}elseif ($t == 2)
{
$this->testRedis(new phpRedisPconn());
}
总次数 | 并发数 | 读写数 | predis | phpRedis | phpRedisPconn | 备注 |
---|---|---|---|---|---|---|
5000 | 100 | 200 | 70982 | 64999 | 62002 | 与上面时间因为执行次数有差别 三者对比即可 |
5000 | 50 | 200 | 62985 | 42004 | 52021 | 这种方案下,connect更快~ |
5000 | 50 | 200 | 74992 | 52001 | 54997 | 又测试了一次 |
5000 | 100 | 20 | 8997 | 7007 | 9997 | 好奇怪~ |
5000 | 100 | 20 | 10999 | 7997 | 11995 | |
5000 | 100 | 2 | 5996 | 4004 | 4996 | |
5000 | 100 | 2 | 5000 | 4998 | 2000 | |
5000 | 100 | 1 | 5000 | 4999 | 1999 | |
5000 | 100 | 1 | 4001 | 2999 | 3997 | |
5000 | 100 | 1 | 7001 | 4996 | 2001 | 猜测是不是跟fpm销毁有关,增加并发总次数(并且修改每次计算毫秒的小数点位数 5位) |
15000 | 100 | 1 | 11995 | 5997 | 5007 | 有差距,但差距不大 |
15000 | 100 | 1 | 11995 | 8005 | 7000 |
在测试中,当高并发时,pconnect 可能会又更好的效果,但是并发低的话,connect会更快一些。
另外,pconnect连接数是和fpm数目相关联的。
参考文章:
高并发下PHP请求Redis异常处理
phpredis中的connect和pconnect
史上最LOW的PHP连接池解决方案
请手动释放你的资源
深入php redis pconnect