在日常运维和开发中,我们经常会用到 Redis 作为缓存或消息存储。但线上偶尔会出现这样一个报错:
[13-Sep-2025 15:59:16 Asia/Shanghai] PHP Warning:
Redis::connect(): connect() failed: Connection timed out in /www/DB/RedisLibrary.php on line 31这是 Redis 连接超时,在某些情况下会导致业务请求失败。本文记录一次排查过程以及优化方案。
一、问题现象
- 错误提示:
Redis::connect() failed: Connection timed out - 触发特征:偶尔发生,不是持续报错。
Redis 监控指标:
connected_clients:1796 blocked_clients:0 used_cpu_sys:5712795 used_cpu_user:4863491看起来连接数和 CPU 占用都不高。
二、初步怀疑方向
- Redis 崩溃/重启?
→ 否,监控显示 Redis 稳定运行,未重启。 - 客户端连接过多?
→ 当前连接数约 1796,远低于maxclients默认上限(10000)。 - CPU 或阻塞问题?
→blocked_clients=0,说明没有命令阻塞;CPU 占用也正常。
因此,问题并不是 Redis 整体挂掉,而是偶发连接超时。
三、深入排查思路
1. 内存与 OOM
此前我们已经遇到过:
OOM command not allowed when used memory > 'maxmemory'Redis 内存接近上限时,写入会卡顿甚至拒绝,导致客户端等待时间变长。
👉 检查 maxmemory 和 maxmemory-policy 配置,确保有合适的淘汰策略(如 allkeys-lru)。
2. 短连接开销
代码里使用的是:
$redis->connect($host, $port, 3.0);这意味着每次请求都要新建 TCP 连接。当并发较高时,大量连接握手容易导致延迟。
👉 建议改为持久连接:
$redis->pconnect($host, $port, 5.0);3. 系统参数限制
即使连接数不高,如果 Linux 内核参数不足,也可能在高峰期丢连接:
ulimit -n文件描述符数太小(需 >= 65535)net.core.somaxconn太低(推荐 >= 1024)net.ipv4.tcp_max_syn_backlog太低(推荐 >= 2048)
👉 可以用以下命令查看:
ulimit -n
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog4. 网络抖动
如果 PHP 与 Redis 不在同一台机器,偶尔的网络延迟或丢包也会触发超时。
👉 可以用 ping 或 mtr 长时间测试,观察网络是否有延迟尖刺。
四、解决方案
Redis 配置优化
CONFIG SET maxmemory 24gb CONFIG SET maxmemory-policy allkeys-lru保证不会因为 OOM 导致阻塞。
客户端优化
- 使用
pconnect代替connect,减少 TCP 握手次数。 - 设置更合理的超时时间,比如
5 秒。 - 增加重试机制,避免偶发超时导致请求失败。
- 使用
系统层优化
- 提高文件句柄数:
ulimit -n 65535 调整 TCP backlog 参数:
sysctl -w net.core.somaxconn=1024 sysctl -w net.ipv4.tcp_max_syn_backlog=2048
- 提高文件句柄数:
监控与预警
- 监控
connected_clients、blocked_clients、latency。 - 配置
slowlog,捕捉耗时命令。
- 监控
五、总结
这次问题的根源不是 Redis 本身崩溃,而是 偶发性的连接超时。常见诱因有:
- 内存逼近上限导致卡顿
- 短连接压力大
- 系统参数不足
- 网络延迟抖动
通过优化 Redis 配置、调整客户端连接方式,以及检查系统内核参数,可以有效减少这种问题的发生。