抽查线上键发现 TTL 全是 -1,内存一天涨了两个 G,写入时代码里明明调过 expire。日志里能对上时间点,这种反而好排。

更新缓存用的是不带后缀的 SET 直接覆盖,SET 会把键上的过期属性一并清掉,只有加 KEEPTTL 或者显式写 EX 才会把过期时间带过去。这一点先确认清楚,后面就不用反复试。

SET product:1001 '{}' KEEPTTL
SCAN 0 MATCH product:* COUNT 1000
TTL product:1001
CONFIG GET maxmemory

「Redis TTL 被覆盖」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。偶发问题先统计频率,一小时几次和一天一次,查法完全不同。

改完顺手把文档补一句,省得下次自己重新推一遍。监控和日志的时间要对上,时区不一致会多绕很大一圈。

临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。

处理上按这个顺序:所有覆盖写改成 SET key value KEEPTTL 保留原有过期时间;用 SCAN 找出 TTL 为 -1 的键 补一次 EXPIRE;把设值和设过期合成一条命令 不要分两次发。

结果对不对很好判断,随机抽十个键查 TTL 都大于 0,第二天内存曲线不再单调上涨。

作者 9823189