"PHP致命错误:未捕获异常'RedisException',消息为'read error on connection'"
这里的驱动程序是phpredis
$redis->blpop('a', 0);
这总是在大约1分钟后超时。我的redis.conf显示超时0,$redis->getOption(Redis::OPT_READ_TIMEOUT)
返回double(0)
如果我这样做,它从未超时$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
为什么我需要-1?Redis文档说Redis.conf中的timeout 0
永远不会让我超时。
"默认情况下,如果客户端空闲数秒,最新版本的Redis不会关闭与客户端的连接:连接将永远保持打开状态。"
据我所知,目前的解决方案是禁用phpredis的持久连接,因为自2011年10月以来,这些连接一直被报告为有缺陷。如果您使用的是php-fpm或其他线程模型,库会专门禁用持久连接。
可以通过调整php.ini default_socket_timeout
值来降低此错误的频率。
此外,phpredis中的读取超时配置并不是普遍支持的。标签2.2.3中介绍了该功能(查找OPT_READ_TIMEOUT
)。
$redis->connect(host, port, timeout1);
$redis->blpop($key, timeout2);
其中timeout1必须长于timeout2。
经过大量的文章研究,并对redis和php进行了自己的研究,这个问题似乎很容易通过这个解决方案解决。在我的用例中,主要的问题是redis服务器无法将进程分叉为将内存中的写入保存到磁盘上的数据库。
我在php.ini和redis.conf中保留了所有的超时值,没有进行建议的修改,然后单独尝试了上面的解决方案,这个问题"连接时读取错误"使用了所有关于在php和redisconf文件中更改超时值的建议都无法解决。
我还看到了一些关于将文件描述符限制提高到100000等的建议。我在云服务器上运行我的用例,文件描述符限制为1024,即使有这个限制,我的用例也能完美运行。
我在php程序中添加了代码ini_set(‘default_socket_timeout’, -1)
,但我发现它不能立即工作。
然而,3分钟后,当我再次开始运行php程序时,我终于找到了原因:redis连接不持久
所以我在redis.conf
中设置了timeout=0
,问题就解决了!
如果你使用的是PHPRedis,在你的PHP代码中,在使用redis longer命令之前添加这一行:
ini_set('default_socket_timeout', -1);
并更改Redis配置文件(/etc/redis.conf
)中的timeout
:
timeout 0