workerman 必须用异步 redis 客户端(如 amphp/redis)配合主动哨兵探测,因 phpredis 同步阻塞且不支持 sentinel 协议解析,无法自动切换主节点;需在 onworkerstart 中定时轮询哨兵、重建连接池并前置 ping 检测。

Workerman 本身不支持 Redis Sentinel 自动发现主节点,必须由客户端显式对接哨兵并手动切换连接;硬套 phpredis 或直接连固定 IP 会彻底失去高可用能力。
为什么 Workerman 不能直接用 phpredis 连 Sentinel?
phpredis 是同步阻塞客户端,一调用 get() 就卡住 event loop,整个 Worker 进程停摆。常见现象包括:Redis::get(): read error on connection、请求堆积、CPU 占满但无响应。Sentinel 的核心价值是故障转移后提供新 master 地址,而 phpredis 完全不感知这个过程——它只会死连旧地址,直到超时或报错。
- phpredis 没有内置 Sentinel 协议解析能力,无法执行
SENTINEL get-master-addr-by-name - 即使你手动轮询哨兵获取地址,phpredis 连接对象也无法热替换(连接池状态无法安全更新)
- Worker 进程复用连接,旧连接断开后不会自动重建,也不会触发重试逻辑
必须用异步 Redis 客户端 + 主动哨兵探测
推荐方案是 amphp/redis(PHP ≥ 8.0)或降级版 amphp/redis:^1.5(PHP 7.4),配合在 onWorkerStart 中启动独立的哨兵探测协程。关键不是“连上 Sentinel”,而是定期刷新 master 地址并重建连接池。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 在
onWorkerStart启动一个常驻Amp\Loop::repeat(),每 3–5 秒执行一次:redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster - 拿到新地址后,销毁旧
RedisClient实例(它不可重用),新建连接并赋值给全局变量(注意线程安全,用static $redis = null+ 双检锁) - 所有业务代码统一从该变量取 client,避免多处 new 实例导致连接爆炸
- 务必在每次
get()/set()前加ping()检测,失败则抛出异常并触发 fallback 逻辑(如降级读本地缓存)
连接断开后不自动重连是最大坑点
amphp/redis 的 RedisClient 实例绑定底层 socket,一旦网络抖动或主从切换,socket 断开后该实例即永久失效——后续所有方法调用都返回 rejected Promise,且不会自动重建。这不是 bug,是设计使然。
- 不能依赖
onResolve回调里的错误处理来“恢复”连接,它只负责本次操作兜底 - 必须把连接健康检查下沉到调用前:先
$redis->ping()->await(),失败就换新 client - 若使用连接池(如
amphp/pool),需自定义Validator实现 ping 检测,否则池中大量 stale 连接会持续拖慢请求 - 哨兵配置中的
sentinel down-after-milliseconds(默认 30000)要和你的探测周期对齐,避免探测太慢错过切换窗口
真正难的不是连上哨兵,而是让每个 Worker 进程在毫秒级内感知 master 变更、安全替换连接、不丢请求也不炸连接数——这些细节没兜住,哨兵就只是个摆设。










