淘汰策略选错会放大缓存穿透风险,因volatile-random/allkeys-random可能误删合法缓存导致重复击穿,volatile-ttl会主动制造伪穿透,noeviction则引发写失败进而全量打库。

高频读写场景下,内存淘汰策略和缓存穿透本质上不冲突,但错误配置会让两者叠加恶化——比如用 volatile-random 淘汰策略 + 未拦截非法 key,可能刚缓存的合法数据被随机删掉,而恶意请求又持续打穿数据库。
为什么淘汰策略选错会放大穿透风险
缓存穿透本身是“查不到、不写缓存”的问题,和内存是否满无关;但一旦你用了不稳定的淘汰策略,就会让本该稳住的合法缓存也变得不可靠:
-
volatile-random或allkeys-random:可能把刚写入的、尚未被高频访问的合法缓存随机干掉,导致下次请求又 miss → 又打库 → 表象上像穿透加剧 -
volatile-ttl:如果热点数据设置了较短 TTL(比如 5 分钟),它反而比冷数据更早被删,等于主动制造“伪穿透” -
noeviction内存满后直接报错OOM command not allowed when used memory > 'maxmemory':写缓存失败 → 后续所有请求都查不到 → 看似穿透,实为配置失当
高频读写下推荐的淘汰策略组合
核心原则:让合法缓存尽量“活下来”,同时不给穿透留空子。不是追求绝对防穿透,而是避免淘汰机制拖后腿:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 纯缓存场景(如 session、token):用
volatile-lru—— 只淘汰带过期时间的 key,永不过期的热点数据(如预热的配置)不会被误伤 - 混存场景(缓存 + 持久化数据共存):用
allkeys-lru,但必须确保热点 key 的EXPIRE时间 ≥ 24h,避免刚重建就被 LRU 判为“冷数据” - 绝对禁用
volatile-random和allkeys-random:随机性在高频场景下等于放弃稳定性 - 内存余量必须留足:通过
INFO memory观察mem_used_human和maxmemory_human,确保使用率 ≤ 80%,否则 LRU/LFU 统计不准,淘汰行为会飘
穿透防护不能只靠淘汰策略,得加一层兜底
淘汰策略管的是“已有缓存怎么留”,穿透防护管的是“不该来的请求怎么拦”。高频读写下二者必须配合:
- 对非法/不存在 key,统一返回空值并缓存(
SET key "" EX 60),但要加前缀隔离,比如nil:user:123456,避免污染主 key 空间 - 布隆过滤器适合写少读多场景;高频写入时注意其误判率上升、扩容成本高,不如先用空值缓存 + 监控
KEYS nil:*命中率来判断是否真需升级 - 应用层做参数校验:比如 ID 字段限制长度、格式、范围,从源头过滤掉
productId=9999999999这类明显异常值
真正容易被忽略的点是:淘汰策略生效的前提是内存真的触达 maxmemory,而穿透发生时 Redis 往往远未满载。所以别幻想调个 allkeys-lfu 就能防穿透——它解决不了“key 不存在”这个根本问题,只负责不让“存在的 key”轻易消失。










