这个坑值得记一笔。Redis 7.0 用来存 RAG 的整段答案,maxmemory 一直没配,used_memory 涨到 8G 后开始用 swap,接口 P99 从 80ms 涨到 3 秒,最后被内核 OOM kill。
刚开始盯着「value 里存了整段 HTML,单条最大 2MB」,折腾了半个多小时,排掉了。
真正麻烦的地方在于,几个原因的现象几乎一样。没有设置 maxmemory,Redis 会一直吃到系统内存耗尽;淘汰策略是默认的 noeviction,写满后直接报错;所有 key 都没有 TTL,旧答案永远不淘汰。
上来先看内存和淘汰策略
redis-cli INFO memory | Select-String 'used_memory_human|maxmemory_human'
接着设置上限并切到 allkeys-lru
redis-cli CONFIG SET maxmemory 4gb; redis-cli CONFIG SET maxmemory-policy allkeys-lru
扫描大 key 找出体积异常的条目
redis-cli --bigkeys
给答案类 key 统一补 7 天过期
redis-cli --scan --pattern 'ans:*' | ForEach-Object { redis-cli EXPIRE $_ 604800 }
改之前我把相关日志按时间截了一段存着,事后对时间线用得上。
中途换过一次思路,把范围缩到最小的那一层,反而快了。
改完先别撤,确认这几项。maxmemory 生效后 used_memory 稳定在 3.8G 左右,P99 回到 90ms,写入不再报 OOM command not allowed,大 key 扫描也没有超过 100KB 的条目。
缓存一定要有上限和淘汰策略,noeviction 在写满那天才暴露,配合 TTL 才能让内存曲线可预测。报错文案容易误导,真正的原因往往在相邻那一层的日志里。
