Workerman协程中Redis频繁read timeout的根本原因是Predis默认启用读写超时,导致空闲连接被服务端或中间设备断开;若使用predis/predis,必须设read_write_timeout=0,或改用workerman/redis客户端并确保Redis服务端timeout=0。

Workerman协程环境下与Redis交互时频繁触发read timeout或“Error while reading line from the server.”错误,本质是Predis默认启用连接读写超时机制,而协程长期挂起期间TCP连接空闲,被Redis服务端主动断开或中间网络设备中断,导致后续读取失败。
确认是否使用Predis而非原生Redis扩展
Workerman官方workerman/redis客户端(v2.0+)基于协程驱动,不依赖Predis;若项目中手动引入predis/predis,则必须显式关闭其超时控制——这是绝大多数超时问题的根源。
检查composer.json:若存在"predis/predis": "^1.1"或类似行,即为Predis路径;若仅含"workerman/redis": "^2.0",则跳过本节,直接进入下一部分。
方法一:Predis客户端禁用读写超时(关键修复)
在创建Predis Client实例时,必须将read_write_timeout参数设为0或-1,否则协程等待期间连接会被强制中断。
【必须设置read_write_timeout=0,否则协程中首次长时间等待后必报错】
修改初始化代码,将URL连接字符串末尾追加?read_write_timeout=0:
$redis = new Predis\Client('tcp://127.0.0.1:6379?read_write_timeout=0');
若使用数组配置方式,需显式传入'read_write_timeout' => 0:
$redis = new Predis\Client([ 'scheme' => 'tcp', 'host' => '127.0.0.1', 'port' => 6379, 'read_write_timeout' => 0 ])
方法二:改用Workerman原生协程Redis客户端(推荐)
该客户端专为Workerman协程设计,自动复用连接、无超时中断风险,且支持同步调用语法(内部非阻塞)。
第一步:安装适配版本
composer require workerman/redis:^2.0
第二步:在onWorkerStart中初始化客户端
$worker->onWorkerStart = function () { global $redis; $redis = new Workerman\Redis\Client('redis://127.0.0.1:6379'); };
第三步:在onMessage等回调中直接调用,无需回调函数即可获得返回值
$result = $redis->get('user:1001');
注意:psubscribe和subscribe命令不支持此协程客户端,如需发布订阅功能,须切换回Predis并严格配置超时参数。
验证连接稳定性
① 启动服务后,执行一次set再立即get,确认基础通路正常
② 模拟长耗时协程:在onMessage中插入usleep(5000000)(5秒挂起),之后再调用$redis->ping(),观察是否仍返回+PONG
③ 若仍失败,检查Redis服务端timeout配置项是否为0(表示永不超时断连),非0值需同步调整为0
【Redis配置文件中timeout必须为0,否则即使客户端设0,服务端仍会主动踢掉空闲连接】











