协程Redis断线重连需保障原子性:执行前检查连接,WATCH-MULTI-EXEC须封装为可重试函数;优先用SET NX EX等原子命令或Lua脚本替代多命令事务;连接池中确保协程间状态隔离。

PHP 协程环境下使用 Redis 客户端(如 swoole + co\Redis 或 hyperf/redis)时,断线重连本身不难,但要保障命令的原子性——尤其是涉及多条命令组合(如 WATCH/MULTI/EXEC、SETNX+EXPIRE)——必须在重连逻辑中避免状态丢失和命令拆分。
协程 Redis 客端断线检测与自动重连
协程 Redis 客户端通常不内置“透明重连”,需主动判断连接状态并重建连接。关键点是:不能在命令执行中途重连,也不能让重连覆盖未完成的事务上下文。
- 每次执行命令前,用
$redis->isConnected()检查(co\Redis支持);若断开,调用$redis->connect()重连 - 对
hyperf/redis,推荐使用Pool+ 自定义Factory,在create()中捕获RedisException并重试连接 - 避免在
MULTI后、EXEC前发生重连——此时连接中断会导致事务上下文丢失,必须回滚重试整段逻辑
保障 WATCH-MULTI-EXEC 原子性的重试策略
WATCH 是乐观锁,依赖连接内状态。一旦连接断开,WATCH 的 key 监控失效,EXEC 必然失败(返回 false)。此时不能简单重连后重发 EXEC,而应完整重试整个流程。
- 将
WATCH→MULTI→ 业务命令 →EXEC封装为一个可重入函数,设置最大重试次数(如 3 次) - 每次重试前,先检查连接;若断开则重连,并清空旧连接残留(
unset($redis)+ 新建实例更安全) - 在
EXEC返回false时,不报错,而是触发下一轮重试(可能因并发修改导致失败,非仅断线)
替代方案:用单命令保证原子性,规避重连风险
能用原子命令解决的,就不要依赖多命令+事务。这既简化逻辑,也天然规避重连带来的状态断裂问题。
立即学习“PHP免费学习笔记(深入)”;
- 用
SET key value EX 60 NX替代SETNX+EXPIRE,一条命令完成加锁与过期 - 用
INCRBY、DECRBY、HINCRBY等原子计数操作,避免GET+SET拆分 - 用 Lua 脚本封装复杂逻辑(如限流、库存扣减),通过
EVAL一次性提交,Redis 保证脚本内执行原子性
连接池场景下的连接复用与状态隔离
在 Hyperf/Swoole 连接池中,连接被复用,但每个协程应持有独立的 Redis 实例或明确绑定连接,防止 A 协程重连影响 B 协程的 WATCH 状态。
- Hyperf 推荐使用
RedisFactory::get()获取新连接,而非复用全局实例 - 在协程结束时(如
defer或finally),显式释放连接($pool->release($connection)),避免连接处于半断开状态被下次误用 - 对需要长时
WATCH的场景,考虑改用消息队列或数据库行锁,避免 Redis 连接生命周期成为瓶颈



















