切换 Redis 后页面偶发 500,日志出现 Connection timed out。重启 Redis 后暂时恢复,并不能证明 Redis 软件本身有缺陷。超时可能发生在建立 TCP 连接、等待命令响应或读取数据,每一种都对应不同指标。

先识别出问题的是哪个用途

Magento 常把 default cache、page cache 和 session 放到不同 Redis DB 或实例。页面缓存超时可能导致后端变慢,Session 超时会让登录、购物车直接失败。根据异常堆栈中的 frontend/resource 与 env.php 配置确认实例,日志中不要输出密码。

redis-cli -h REDIS_HOST -p 6379 PING
redis-cli -h REDIS_HOST -p 6379 INFO clients
redis-cli -h REDIS_HOST -p 6379 INFO stats
redis-cli -h REDIS_HOST -p 6379 INFO persistence

从与 PHP-FPM 相同的网络环境测试。运维机 PING 很快,不代表应用容器到 Redis 的路径正常。

连接数耗尽时,重启只是清场

观察 connected_clientsrejected_connectionsblocked_clients 与 maxclients。PHP-FPM worker 数、后台消费者和 Cron 会共同建立连接。错误的持久连接使用、连接未及时释放或突发扩容都可能冲过上限。

不要只把 maxclients 调大。操作系统文件描述符、Redis 内存和客户端并发也要匹配;连接数增长曲线若不随请求结束回落,应查客户端库和进程生命周期。

慢命令与大 Key

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

KEYS * 会阻塞大型实例,不要用于生产排查。需要观察 Key 分布时使用受控 SCAN 或离线工具。巨型 Session、缓存标签集合和一次删除大量 Key 都会造成延迟尖峰。

持久化和内存压力

RDB fork、AOF rewrite、内存 swap、淘汰风暴会让响应暂停。查看 latest_fork_usec、used_memory、used_memory_rss、evicted_keys 与主机 I/O。Cache 可以按策略淘汰,Session 实例通常不应随意淘汰活跃会话;两者混用一个内存上限会互相影响。

超时参数不是越大越好

connect timeout 太短会放大轻微网络抖动,read timeout 过长则会占满 PHP worker,让故障扩散。根据正常 P95/P99 延迟与业务容忍度设置,并配合有限重试。非幂等写操作不能在未知结果时无限重放。

验证恢复

在峰值并发下分别测试页面缓存、登录 Session、购物车和后台消费者;观察连接数、延迟、fork 与错误率同一时间轴。修复目标是超时尖峰有明确根因且容量有余量,不是把错误日志通过无限延长 timeout 隐藏。

网络路径与 DNS 也要单独测

使用主机名连接时,容器 DNS 抖动、服务发现切换和跨可用区路由都可能只影响新连接。分别记录 DNS、TCP connect 和 Redis command latency;若已有连接正常、新连接慢,重点不在命令执行。云 Redis 的 TLS 握手、连接代理和故障切换也会产生短时尖峰,客户端必须支持重连但限制重试次数。

Cache 与 Session 的降级策略不同

页面缓存短暂失败可以回源重建,但 Session 写入失败不能悄悄当作空会话,否则客户会登出或购物车丢失。为两个用途使用独立 DB/实例、前缀和监控;容量规划按 PHP-FPM、Consumer、Cron 的总并发计算。发生故障时,应优先保护结账和登录,而不是让缓存预热占满全部连接。

最后做一次受控故障切换,观察客户端能否在旧主节点断开后连接新主节点、是否出现长时间 DNS 缓存,以及恢复期间有没有重复业务操作。只在稳定状态跑压测,无法证明高可用配置真的有效。