直接复用同一个Redis连接会出错,因为协程并发访问共享连接导致命令交错、响应错乱,引发read error或错误数据;必须通过RedisPool::get()获取独占连接并用put()归还,且事务等场景需独占连接避免状态污染。

为什么直接复用同一个Redis连接会出错
协程不是线程,它共享同一进程的内存空间,但每个协程有自己的执行栈。如果你在多个协程里共用一个 Redis 实例(比如全局单例或静态属性),命令会交错写入、响应错乱,最终触发 RedisException: read error on connection 或返回空/错误数据。这不是 Redis 服务端问题,而是客户端缓冲区被并发读写污染了。
RedisPool::get() 必须配对使用 put()
每次调用 $pool->get() 拿到的是独占连接,用完必须显式归还,否则池子会逐渐耗尽——哪怕协程结束,连接也不会自动释放。常见错误是:忘记 put、在异常分支漏掉 put、或误把 null 当有效连接传给 put。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 正确写法:用
try...finally保证归还 - 如果连接中途断开(如超时、服务重启),
put(null)告诉池子丢弃它,池会自动新建一个补位 - 不要在
put后继续调用该连接的任何方法,已失效
连接池配置里最易忽略的三个参数
timeout、connect_timeout 和 db_index 必须和业务匹配,否则会出现“看似连上了却读不到数据”或“brPop 卡死”这类静默故障。
-
timeout控制命令级超时,比如get或set;若设为-1(永不超时),遇到网络抖动会永久阻塞协程 -
connect_timeout是建立 TCP 连接的上限,建议设为1.0秒,避免 DNS 解析慢拖垮整个池 -
db_index默认是0,但如果你业务用了多个 DB(如SELECT 1),必须显式设置,否则所有操作都在 DB 0 上,数据错乱不报错
事务和 pipeline 场景下不能直接用连接池
连接池里的连接是无状态复用的,但 MULTI / EXEC 或 pipeline 要求连接保持上下文。一旦你在 get() 后开启事务,其他协程再从池里拿到这个连接,就会破坏事务隔离。
- 方案一:用
$pool->instance()(部分库支持)获取独占连接,用完$pool->put($conn)归还 - 方案二:改用连接池外的独立
Redis实例处理事务,避免混用 - 切记:事务中发生的异常,连接可能处于不可恢复状态,此时应
put(null)而非put($conn)

















