webman/redis连接池满时不报错而是阻塞等待,需主动监控getstats()中wait值是否持续大于0;根本原因是客户端池配置过小、操作卡住或pipeline未执行,非redis服务端满。

Redis连接池满了,webman/redis 报错却没提示?
Webman 的 webman/redis 扩展默认不抛出“连接池已满”异常,而是阻塞等待——这会让请求卡在 Redis::get() 上,超时后才报 Redis connection timeout 或直接 504。你得主动监控池状态,不能等它崩了才发现。
关键点是:连接池满 ≠ Redis 服务端满,而是客户端本地池子取不到空闲连接。常见原因有三:
-
config/redis.php中'pool' => ['max_connections' => 20]设太小,高并发下全部被占满 - 某次 Redis 操作卡住(如网络抖动、大 key 扫描、慢命令),连接迟迟不归还
- 业务代码里用了
Redis::pipeline()但没调->execute(),连接被 pipeline 持有却不释放
验证方式:在任意控制器中加一行日志:var_dump(Redis::getConnectionPool()->getStats());,输出类似 ['used' => 20, 'idle' => 0, 'wait' => 15] ——如果 wait 持续大于 0,说明已在排队。
mysql 和 redis 连接池并发上限怎么设才不打架?
Webman 多 Worker 共享同一份连接池配置,但每个 Worker 内部会独立维护自己的连接池实例。所以总连接数 ≈ Worker 数 × max_connections。别只看单个池的 max_connections,要算全局压力。
假设你开了 8 个 Worker,Redis 池设了 20,MySQL 池也设了 20,那理论上最大可能建立 160 个 Redis 连接 + 160 个 MySQL 连接。而 Redis 服务端默认 maxclients 是 10000,MySQL 默认 max_connections 是 151 ——后者很容易先爆。
推荐配比(以 8 Worker 为例):
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- Redis 池:
'max_connections' => 12(总连接 ≤ 96,留余量) - MySQL 池:
'max_connections' => 10(总连接 ≤ 80,远低于 MySQL 默认 151) - 务必同步调大 MySQL 服务端
max_connections,否则PDOException: SQLSTATE[HY000] [1040] Too many connections会先报出来
注意:Redis 连接轻量,MySQL 连接重,不要对齐数字。宁可 Redis 池稍大,也不能让 MySQL 池逼近服务端上限。
连接池参数调不对,比不设还危险
webman/redis 底层用的是 predis/predis 或 phpredis,但它的池管理逻辑是自己封装的。几个关键参数不调好,会导致“看着有连接,实际取不到”:
-
'min_connections':设为2起步,避免冷启动时首次请求还要创建连接,增加延迟 -
'max_idle_time':必须设,比如60(秒),否则空闲连接永不释放,长期运行后大量CLOSE_WAIT堆积 -
'timeout':建议设为0.1(秒),不是越长越好。超时短能快速失败,触发重试或降级,而不是卡死整个请求 - 别碰
'retry_times':默认 0,设成 >0 会在失败后反复重试,放大连接池压力
错误示范:'max_idle_time' => 0(永不过期)+ 'max_connections' => 50 → 进程跑一天后,netstat -an | grep :6379 | wc -l 可能飙到三四百,但真正活跃的不到 20。
查连接池是否真溢出,别只盯 PHP 日志
PHP 层面的日志往往只显示超时或失败,但根本原因在连接池内部或服务端。要交叉验证三层:
- 客户端层:执行
php start.php status,看 Summary 里每个 Worker 的内存和连接数趋势;再查Redis::getConnectionPool()->getStats()输出 - Redis 服务层:登录服务器执行
redis-cli info clients | grep connected_clients,对比是否接近maxclients;再用redis-cli client list | wc -l看真实连接数 - 系统层:
ss -s | grep tcp查 TCP 连接总数,cat /proc/sys/net/ipv4/ip_local_port_range看可用端口范围 —— 如果端口快耗尽,TIME_WAIT会堆积,连不上不是池子问题,是系统限制
最容易被忽略的是:Webman 启动后,Redis 连接池不会自动预热。第一个请求来时才会建连接,这时如果 min_connections 是 0,就可能因首次建连慢导致误判为“池满”。上线前手动 curl 一次关键接口,让池子先热起来。










