Magento 2 前台偶发 500,日志中出现 ERR max number of clients reached,说明 Redis 已拒绝新的客户端连接。直接把 maxclients 调大可能短暂恢复,但如果连接持续泄漏或服务器文件描述符不足,问题很快会再次出现。

先确认哪一个 Redis 实例耗尽

Magento 常把 default cache、page cache 和 session 配置到 Redis,它们可能使用同一实例的不同 database,也可能完全分离。查看 app/etc/env.php 中实际主机、端口和 database 编号,不要把敏感密码输出到工单。再从 Redis 查看:

redis-cli INFO clients
redis-cli CONFIG GET maxclients
redis-cli CLIENT LIST

关注 connected_clients、blocked_clients、最长空闲时间和客户端来源地址。database 编号只能隔离键空间,不能隔离连接数和内存;三个用途共享同一进程时,仍共同消耗 maxclients。

PHP-FPM 并发会放大连接数量

每个 PHP-FPM worker 可能同时持有缓存、FPC 和 session 连接。Web 节点数量、pm.max_children、Cron 与消费者进程相加后,理论连接上限可能远高于单机观察值。先估算所有节点最大并发,再与 Redis、操作系统文件描述符限制比较。

redis-cli INFO clients | grep connected_clients
redis-cli INFO stats | grep rejected_connections
ulimit -n

如果 rejected_connections 持续增加,说明不是一次偶发峰值。不要只在 Redis 提高 maxclients,系统的 nofile 限制和服务单元限制也必须能支持新值。

区分连接过多与命令太慢

慢 Lua、巨大的 tag 清理或阻塞命令会让连接长时间占用。检查 slowlog、命令统计和延迟:

redis-cli SLOWLOG GET 20
redis-cli INFO commandstats
redis-cli --latency

Magento 缓存清理在键量很大时可能造成峰值;session 数据过大、机器人制造大量会话,也会增加内存与连接压力。若 CLIENT LIST 中大量连接来自未知主机,检查网络访问控制,Redis 不应直接暴露到公网。

持久连接不是越多越好

某些客户端支持 persistent connection。它能减少频繁建连,但配置不当会让每个 worker 长期占用多条连接。比较启用前后的连接曲线,并确认连接 ID 或持久标识不会在 cache 与 session 间冲突。升级客户端库后出现问题,还应核对 phpredis、Magento 版本和连接参数兼容性。

必要时将 session、default cache 和 page cache 分到独立 Redis/Valkey 实例,以隔离内存和故障域,但迁移要安排维护窗口并考虑现有会话失效。缓存实例通常可以重建,session 丢失会让客户退出登录,两者风险不同。

修复后在正常流量和 Cron 高峰观察 connected_clients、rejected_connections、内存、命令延迟和 PHP-FPM 队列。只有连接数在可预测范围内回落,并且没有新的拒绝记录,才说明不是单纯把上限往后推。