$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端就会因超时异常退出。可以自行设置延长超时时间或永不超时。

问题描述redis提供了pub/sub功能,但在使用phpredis的subscribe时发现这样一个问题,代码如下(sub.php):<?php/*监听demo频道,打印收到的信息*/function process($redis, $chan, $msg){ var_dump($msg);}$redis = new Redis();$res = $redis->connect(' 4、多对多消息传递 消息传递这一应用广泛存在于各个网站中,这个功能也是一个网站必不可少的。常见的消息传递应用有,新浪微博中的@我呀、给你评论然后的提示呀、赞赞赞提示、私信呀、甚至是发微博分享的新鲜事;知乎中的私信呀、live发送过来的消息、知乎团队消息呀等等。 2、实现方法 消息传递即两个或者多个客户端在相互发送和接收消息。 通常有两种方法实现: 第一种为消息推送。 Redis 内置有这种机制,publish往频道推送消息、 subscribe 订阅频道。这种方法有一个缺点就是必须保证接收者时刻在线(即是此时程序不能停下来,一直保持监控状 $ redis = new Redis (); $ redis ->connect('127.0.0.1',6379); function f($ redis , $channel, $message)
项目中利用gearman实现异步处理,worker端涉及对mysql数据库及 redis 缓存的一系列操作,但是在实际的使用中发现很短时间后就会退出,开始查看log也没什么异常,通过程序端设置set_time_limit(0), try/catch 捕获异常、服务器端查看日志,通过strace 跟踪进程执行时的系统调用等等也没有什么改善, 问题 依旧,一时感觉很是无解啊。        折腾至最后简化worker端功能,只简单实现 redis 的List 链表新增一项功能,结果没多长时间服务又停止了。这次查看日志
解决 php操作 redis 报:Fatal error: Uncaught exception ' Redis Exception' with message ' Redis server went away'
Redis 的发布订阅(Pub/Sub)是一种消息通信模式,它支持订阅者向订阅的频道发送消息,以及订阅者向订阅的频道订阅消息。 在 Redis 中,使用 PUBLISH 命令可以将消息发布到频道,而使用 SUBSCRIBE 命令可以订阅频道。当频道有消息发布时,订阅了该频道的客户端将收到消息。 例如,在 redis -cli 中,你可以这样使用发布订阅功能: 1. 开启一个新的 redis -cli 会话,并使用 SUBSCRIBE 命令订阅一个频道: redis -cli > SUBSCRIBE channel-name 2. 在另一个 redis -cli 会话中,使用 PUBLISH 命令向频道发布消息: redis -cli > PUBLISH channel-name "Hello, world!" 在第一个 redis -cli 会话中,你将看到如下输出: Reading messages... (press Ctrl-C to quit) 1) " subscribe " 2) "channel-name" 3) (integer) 1 4) "message" 5) "channel-name" 6) "Hello, world!" 这意味着订阅者已成功收到了发布者发布的消息。