workerman中redis连接必须在onworkerstart中初始化,每个worker进程持有独立连接;禁用read_write_timeout=0防空闲断连,配合ping检测与重建失效连接。

Workerman里Redis连接必须在onWorkerStart中初始化
每个Worker进程必须持有独立的Redis连接,不能在全局或onConnect里创建。否则多个连接共享fd、互相干扰,轻则报Connection refused,重则进程崩溃。
常见错误是把$redis = new Redis()写在start.php顶层,或者在onMessage里每次新建——这会导致连接数爆炸、端口耗尽、认证失败。
- 正确做法:在
$worker->onWorkerStart回调中创建并赋值给静态变量或闭包引用 - 务必显式调用
$redis->connect()和$redis->auth()(如果启用了密码) - 不要复用
new Redis()实例跨进程,也不要试图用static $redis在类方法里懒加载
Predis\Client连接断开主因是read_write_timeout默认值
用Predis\Client时,运行几小时后出现error while reading line from the server,基本就是这个参数在作怪。它默认是60秒,空闲超时后底层socket被关闭,但Predis不自动重连。
解决方式不是加定时器去ping,而是从连接源头禁用超时:
- 构造Client时传参:
new Predis\Client('tcp://127.0.0.1:6379?read_write_timeout=0') - 或用数组配置:
new Predis\Client(['scheme' => 'tcp', 'host' => '127.0.0.1', 'port' => 6379, 'read_write_timeout' => 0]) - 注意:设为
-1在某些Predis版本下无效,0最稳
Redis断线检测与惰性重连要分两层做
即使设了read_write_timeout=0,网络抖动、Redis重启、防火墙中断仍会导致连接失效。不能靠try/catch捕获所有异常——比如Redis::ping()失败只抛Notice,catch不到。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
推荐组合策略:
- 执行关键操作前,先用
$redis->ping() === false判断是否断连(注意返回false而非抛异常) - 若断连,立刻
unset($redis)再重建新实例,避免复用已损坏的句柄 - 业务逻辑里对
RedisException做兜底:捕获Redis server went away等错误码,触发重试流程 - 不要在
onClose或onMessage里做重连,必须回到onWorkerStart上下文或封装成独立重连函数
PHP版本和Redis扩展不匹配会直接导致Class 'Redis' not found
尤其在phpenv、phpstudy这类多版本环境中,php -m | grep redis显示有,但Workerman启动时报错,大概率是CLI模式加载了错误的php.ini或扩展路径不对。
验证和修复步骤很具体:
- 查Workerman实际用的PHP路径:
which php,再php -i | grep 'Loaded Configuration File' - 确认该
php.ini里有extension=redis.so,且extension_dir指向正确的so文件目录 - Windows下phpstudy 8.0自带Redis 3.0,不支持自动重连,必须换用≥3.3.x版本(如tporadowski/redis release)
- 扩展和Predis不要混用:同一进程里别同时
require redis.so又use Predis\Client
连接池不是必需项,但连接生命周期管理是硬门槛——漏掉onWorkerStart初始化或忽略read_write_timeout,服务跑半天就静默挂掉,日志里连错误都不留。










