他的回复:
先说结论:题干里“重启能好一会儿、过段时间又来”是最有价值的线索。它说明故障会随时间累积,根因大概率不在 Redis 实例本身,而在客户端侧——连接泄漏、空闲连接被中间设备掐断、连接池被打满三者之一。下面这套方法重点补前面回答较少提到的服务端诊断命令和 Jedis/Lettuce 的客户端差异,照着走基本不用猜。一、先把“超时”定性:三种报错,三条排查线同样是“连接缓存超时”,报错关键字不同,病因完全不同:1. connect timed out / Unable to connect:TCP 连接根本没建上,先查网络与实例可达性,不要去查慢日志。2. Read timed out / socket timeout:连接已经建好,但命令迟迟没有返回,先查慢命令、阻塞命令和实例负载。3. Could not get a resource from the pool / 获取连接等待超时:根本没拿到连接,先查连接池与连接泄漏,Redis 本身可能一点都不慢。第一步就做错,后面全白忙。先把完整异常堆栈(含 host、port、耗时、发生时刻精确到秒)保存下来,后面要和 DCS 控制台的监控曲线按分钟对齐。二、十分钟定位法:三条命令钉死故障在哪一跳1. 绕开业务代码做直连对照。在应用所在的那台 ECS 上,用 redis-cli 直连 DCS 实例的内网地址,先跑 PING,再跑一条业务里最常用的读命令,各跑三遍记下耗时。直连也慢,问题在实例侧或网络;直连很快、应用超时,问题就在客户端或连接池。DCS 集群加 Proxy 模式要连控制台给出的 Proxy 地址,用单机客户端直连某个分片会出现偶发超时或 MOVED。2. 看服务端连接状态。执行 INFO clients,看 connected_clients 是否接近 maxclients,同时看 blocked_clients 是否大于 0(大于 0 说明有客户端正被 BLPOP 之类的阻塞命令挂住)。再执行 CLIENT LIST 看每个连接的空闲时长(idle 字段),idle 特别大又突然超时的连接,多半是被中间设备掐断的僵死连接。3. 看慢日志。执行 SLOWLOG GET 20,对照超时发生的时刻,看前后有没有 KEYS、大 key 的 HGETALL、超大集合的 SMEMBERS、耗时 Lua 脚本。生产禁用 KEYS,改用 SCAN 分批;大 hash 用 HSCAN,别一次全量取回。三、客户端侧最容易漏的三处1. 连接归还是第一嫌疑人。重点查异常分支:try-with-resources、finally 里有没有漏关;异步任务、定时任务里有没有每次新建连接却不关闭。Jedis 的连接不是线程安全的,用完必须归还;Lettuce 默认共享单连接,误把它当 Jedis 那样每次新建连接用完不关,同样会把连接数打满。看 DCS 控制台连接数曲线:重启后从低位一路爬升、高峰顶到上限,基本是泄漏;只在高峰尖峰、平时回落,更像池子配小了。2. 空闲连接被中间设备掐断。即使没有泄漏,长时间空闲的连接也可能被 NAT、安全组或负载设备静默回收,客户端还以为连接可用,下一次复用它发命令就超时。对策是打开连接池的空闲检测(testWhileIdle)与空闲回收,让池子定期探活并淘汰僵死连接。3. 超时过的连接不要还回池里。Jedis 里一条命令超时后,这条连接的状态已经不可信,直接还回池子会让后面的请求连续超时,正确做法是标记为 broken 并丢弃重建。应用线程池打满或一次长时间 GC 停顿同样会让请求集体超时,日志看起来也像 Redis 超时,要同时看应用侧线程池队列与 GC 停顿再下结论。四、服务端侧:大 key 与阻塞命令Redis 是单线程模型,一条慢命令会拖住所有排队命令。业务低峰用 redis-cli --bigkeys 扫一遍大 key 分布,对超过几 MB 的 value 用 MEMORY USAGE 确认大小,考虑拆 key、压缩 value 或加本地缓存。删除大 key 不要用 DEL 同步删,改用 UNLINK 异步删除。还要留意 BGSAVE、AOF 重写期间的 CPU 与磁盘 IO 尖峰。五、参数怎么配:成套调,不要只调一个连接超时建议 2~5 秒,只管建连;读写超时建议 3~10 秒,且必须大于最慢业务命令的 P99;连接池 maxTotal 按高峰并发留余量,maxWait 一定要设上限,避免请求无限排队把业务线程池拖垮;只对幂等读命令做有限重试(1 次为宜),写命令先确认幂等再重试,否则高峰期重试会把流量再放大一倍。六、验证与防复发:把四条曲线做成告警调完不要只看“不报错了”。用云监控 CES 把连接数、等待连接的线程数、慢日志条数、CPU 使用率做成告警,修复后观察一个完整高峰周期:连接数不再持续爬升、超时报错不再出现、慢日志里没有新的大 key 慢命令,才算真正解决。常见误区再强调三点:只把超时时间调大,会让请求在池里排更久;只重启应用,会清掉已泄漏的连接,但泄漏源还在;只升级实例规格,如果根因是连接泄漏或慢命令,规格升上去照样会在高峰时超时。按“记报错类型与精确时刻 → 直连对照 → 看连接数曲线 → 查慢日志与大 key → 查代码归还 → 最后成套调参”走一遍,基本能定位到具体一层。