predis 实现 phpredis 的 pconnect 方法
predis和phpredis都是redis的php客户端,区别如下
Redis的PHP客户端rediska、phpredis、predis
Redis支持的客户端种类非常多,包括C、Java、PHP、Python等,本文主要介绍PHP客户端的安装和使用。
Redis的客户端实际上担负了通过网络协议与Redis Server进行通信的过程,通信的过程必须遵循协议规范,让客户的调用更加符合特定语言的使用习惯。
现有PHP客户端:rediska、phpredis、Predis,这些客户端中,有纯PHP的实现方案,也有二进制版本的实现方案。
rediska 官网:https://github.com/shumkov/rediska
predis 官网: https://github.com/nrk/predis
phpredis 官网:https://github.com/phpredis/phpredis
rediska、phpredis、predis 对比
官方提供的PHP客户端列表如下:
- | predis | phpredis | rediska |
---|---|---|---|
易扩展 | ∆ | ∆ | |
客户端策略和Hash算法定义 | ∆ | ∆ | |
实现方式 | 纯PHP | PHP扩展(C语言) | 纯PHP |
测试数据(本地环境下) | 18900 SET/sec using 12 bytes for both key and value | 29000 SET/sec using 12 bytes for both key and value | |
18300 GET/sec while retrieving the very same values | 30000 GET/sec while retrieving the very same values | ||
0.210 seconds to fetch 30000 keys using KEYS *. | 0.037 seconds to fetch 30000 keys using “KEYS *”“. | ||
测试结果(网络环境下) | 3150 SET/sec using 12 bytes for both key and | 3300 SET/sec using 12 bytes for both key and | |
3150 GET/sec while retrieving the very same | 3300 GET/sec while retrieving the very same | ||
0.212 seconds to fetch 30000 keys using “KEYS *”. | 0.088 seconds to fetch 30000 keys using “KEYS *”. |
predis
Predis是一个灵活和特性完备(PHP>5.3)的支持Redis的PHP客户端。
当前版本为0.6.3,默认不支持PHP5.2,主要特性如下:
1. 完整的支持从1.2到2.4的Redis,并且支持当前正在开发的版本;
2. 提供客户端实现的一致性哈希算法,支持自定义;
3. 在单个或聚合连接中支持命令管道;(Command pipelining on single and aggregated connections)
4. 能够通过TCP/IP或者Unix domain sockets连接到redis,支持持久连接;
5. 自动连接Redis实例,使用“懒惰”方式,只在第一个命令发出时执行连接;
6. 可以灵活定义客户端的命令集合;
phpredis
这是一个二进制版本的PHP客户端,按照的说法,效率要比Predis高。
这个版本支持作为Session的Handler。
这个扩展的优点在于无需加载任何外部文件,使用比较方便。
缺点在于难于扩展,一般的PHP程序员无法对其做出扩展。
考虑到Redis正在飞速发展过程中,缺乏扩展的特性还是有些影响的,需要维护过程中注意进行升级更新。
Rediska
rediska 目前(2011年)还处于 beta 阶段。好久没人维护了,不推荐
他的代码托管在github上,可以方便的获取。
另外也提供了PEAR版本,所以获取和安装都非常方便。可以使用PEAR包安装。
phpredis是php扩展由C语言编写,诞生较早,很多PHPer都熟悉。
predis是用PHP语言编写,由于最近几年composer的盛行,以及很多框架的支持composer,存于composer库的predis也被大量应用。
pconnect()是phpredis里的方法,区别于connect(),详细可以看米扑博客《PHP 高并发下请求 Redis 异常处理》
总结就是pconnect方法建立后的连接并不随这请求的结束而关闭,而是依赖于php-fpm进程,php-fpm进程不死,redis connect就一直存在,直到空闲超时自动断开。
也就是建立了持久连接,适用于高并发下PHP请求Redis。
但是predis没有pconnect()方法,该如何实现类似的功能呢?
项目使用的是Laravel框架,但是在文档中并没有找到相关的配置参数。
于是只能读插件源码,最后在/src/Connection/StreamConnection.php
类中找个了实现连接redis的方法:
/** * Initializes a TCP stream resource. * * @param ParametersInterface $parameters Initialization parameters for the connection. * * @return resource */ protected function tcpStreamInitializer(ParametersInterface $parameters) { if (!filter_var($parameters->host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $address = "tcp://$parameters->host:$parameters->port"; } else { $address = "tcp://[$parameters->host]:$parameters->port"; } $flags = STREAM_CLIENT_CONNECT; if (isset($parameters->async_connect) && $parameters->async_connect) { $flags |= STREAM_CLIENT_ASYNC_CONNECT; } if (isset($parameters->persistent)) { if (false !== $persistent = filter_var($parameters->persistent, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)) { $flags |= STREAM_CLIENT_PERSISTENT; if ($persistent === null) { $address = "{$address}/{$parameters->persistent}"; } } } $resource = $this->createStreamSocket($parameters, $address, $flags); return $resource; }
在第19行的 $parameters->persistent
可以看到一个陌生的参数persistent
,翻译为‘持久’。
所以只要在使用predis连接redis的时候,加上参数persistent,并赋给一个true或1,就可以实现phpredis的pconnect(),简单方便。
下边是邮件佐证,说明没有错误理解源码:
Can the predis support the function pconnect() which in php-redis? Yes, just add in the connection parameters persistent=1 (when using URI strings) or persistent => true (when using a named array).
这个坑是怎么踩到的呢?
还是因为框架文档的原因,目前很多PHP框架都已经支持了composer,如Laravel,Yii,CI等,但是并不能保证文档及时更新,尤其是中文文档,所以还是要有阅读源码的能力。
其实从上边的代码中还可以看到很多内容:
-
predis使用了tcp的方式连接redis,主要用到的函数是
stream_socket_client
(predis还有一种http的方式连接redis,主要用curl,不在这个类中)。 - predis并不依赖phpredis。很多项目环境安装了phpredis又在框架里安装了predis,就以为后者依赖前者,这是错误的。
- 在上述代码第16行还可以看到另一个参数async_connect,用于异步连接,也很重要,但是在很多文档里都没有介绍。
参考推荐:
phpredis 中的 connect 和 pconnect
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2018-03-31 05:29:12
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!