应直接使用 swoole\database\redispool,它自v4.4.13内置,基于channel实现自动调度、断线重连、连接数限制与超时控制,比手写更稳定可靠。

直接用 Swoole\Database\RedisPool,别自己手写
官方从 v4.4.13 就内置了 RedisPool,它基于 Channel 自动调度,自带断线重连、连接数限制、超时控制,比手写 SplQueue + 手动 connect 更稳。自己实现容易漏掉健康检查、异常归还、池大小动态伸缩这些细节。
常见错误现象:get() 卡住、协程阻塞、连接数暴涨、ERR max number of clients reached 报错——基本都是没用对池,或没配好最大连接数。
-
RedisPool构造必须传RedisConfig和size(比如32),不传 size 默认 64,高并发下可能不够用 - 连接失败时,
get()会等待直到有可用连接或超时(默认 0.1 秒),不是立刻返回 false - 必须调用
put($redis)归还,否则连接泄露;若连接已异常(如断连后执行命令报错),要put(null)补位,否则池里少一个可用连接
get() 和 put() 必须成对出现在同一个协程内
连接池不是全局共享资源池,而是协程安全的 Channel 队列。每个 get() 拿到的 \Swoole\Coroutine\Redis 实例只能由当前协程使用,不能跨协程传递或缓存。
使用场景:HTTP 请求处理、WebSocket 消息响应、定时任务回调等——所有在 go() 或事件回调里跑的逻辑。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 错误写法:
$redis = $pool->get(); go(function() use ($redis) { $redis->get('x'); });—— 跨协程用了同一连接对象,极大概率触发连接状态错乱 - 正确写法:在同一个匿名函数里完成
get → 操作 → put - 不要在
onWorkerStart里预取连接并存为静态变量,协程上下文不一致,会出错
连接池要配合 workerExit 清理,否则 reload 失败
连接池里的连接是长连接,进程退出时不显式关闭,系统 TCP 连接不会立即释放,下次 reload 可能因端口/连接数占满起不来。
性能影响:不清理会导致 TIME_WAIT 连接堆积、内存缓慢增长、reload 超时失败。
- 在
onWorkerExit回调里调用$pool->close(),这是最稳妥的做法 - 如果用了
reload_async => true,更要确保close()执行完成再退出,否则新 worker 启动时旧连接还在占用资源 - 不要依赖 PHP 析构函数自动回收,协程对象生命周期不可控
连接池初始化时机和配置项很关键
连接池对象本身是普通 PHP 对象,但内部的连接是在首次 get() 时才真正建立的。提前 fill() 可以避免首请求延迟,但填太多又浪费资源。
参数差异:RedisConfig 支持 host、port、timeout、auth、db 等,但不支持 Unix Socket(目前仅限 PDOConfig)。
- 建议上线前用
$pool->fill(8)预热,尤其在onWorkerStart里做 -
timeout设太小(如 0.01)会导致频繁重连;设太大(如 5)会让故障感知变慢,推荐 0.3~1.0 秒 - 连接池
size不是越大越好,需按压测结果调:单机 Redis 建议 ≤ 256,集群分片后可适当放宽
INCR,仍需靠 Lua 脚本或事务保证原子性。池只管连接复用,不管业务逻辑一致性。










