首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >phpredis subscribe超时问题及解决

phpredis subscribe超时问题及解决

作者头像
跑马溜溜的球
发布2020-12-07 15:33:46
1.2K0
发布2020-12-07 15:33:46
举报
文章被收录于专栏:日积月累1024日积月累1024

问题描述

redis提供了pub/sub功能,但在使用phpredis的subscribe时发现这样一个问题,代码如下(sub.php):

<?php
/*监听demo频道,打印收到的信息*/
function process($redis, $chan, $msg){
    var_dump($msg);
}

$redis = new Redis();
$res = $redis->connect('127.0.0.1', '7979');
$redis->subscribe(array('demo'), 'process');

代码运行后,发现如果在一段时间内未收到来自demo频道的消息,则会报如下错误:

PHP Fatal error:  Uncaught exception 'RedisException' with message 'read error on connection' in sub.php:11
Stack trace:
#0 /search/ballqiu/sub.php(11): Redis->subscribe(Array, 'process')
#1 {main}
  thrown in sub.php on line 11

原因分析

为了查找原因,我们使用strace对代码进行了跟踪:

strace php sub.php

截取部分重要输出如下:

//连接redis
connect(3, {sa_family=AF_INET, sin_port=htons(7979), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
//发送subscribe命令
sendto(3, "subscribe  demo\r\n", 17, MSG_DONTWAIT, NULL, 0) = 17
//收到响应
recvfrom(3, "*3\r\n$9\r\nsubscribe\r\n$4\r\ndemo\r\n:1\r"..., 8192, MSG_DONTWAIT, NULL, NULL) = 33
poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
//套机字超时时间设为60s
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 0 (Timeout)
//等待超时,关闭连接
close(3)                                = 0
//输出错误信息
write(2, "PHP Fatal error:  Uncaught excep"..., 261PHP Fatal error:  Uncaught exception 'RedisException' with message 'read error on connection' 

可见报错的本质是poll设置接收超时所致,从starce结果我们知道这个超时默认是60s

解决

我们有两种方法改变超时 - 方法1 在代码起始处设置

ini_set('default_socket_timeout', -1);
  • 方法2 在redis connect后执行
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);

两种方法中的-1均表示永不超时,你也可以将超时设置为自己希望的时间。 无论使用哪种方法,再次strace, 你会发现poll的超时被设为了-1。

recvfrom(3, "*3\r\n$9\r\nsubscribe\r\n$4\r\ndemo\r\n:1\r"..., 8192, 0, NULL, NULL) = 33
poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
//超时被设为-1, 即永不超时
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, -1

个人比较推荐方法2,它只影响到redis本身。而方法1会对其它方法产生影响,比如 file_get_contents等。

总结

使用phpredis的subscribe时,默认60内没有收到消息,sub端就会因超时异常退出。可以自行设置延长超时时间或永不超时。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-09-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题描述
  • 原因分析
  • 解决
  • 总结
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档