redis内存淘汰策略不直接导致缓存穿透或击穿,但会放大其影响:volatile-lru易致热点key提前淘汰引发击穿;allkeys-random使空值缓存失效加剧穿透;noeviction下oom错误可能绕过缓存直连db;淘汰与过期机制协同生效,需结合监控与合理选型。

Redis内存淘汰策略本身不直接导致缓存穿透或击穿,但会放大它们的影响——尤其是当淘汰策略与过期策略混用、或配置不当的时候。
volatile-lru 为什么会让缓存击穿更难防
如果你对热点 key 设置了 EXPIRE,又启用了 volatile-lru 淘汰策略,那这个 key 可能还没到 TTL 就被提前淘汰(比如内存紧张时)。结果就是:你本以为“有 TTL 保护”,实际却提前失效,且无锁保护的读请求直接打穿到 DB。
-
volatile-lru只看「设置了过期时间」+「最近最少用」,不区分冷热;热点 key 如果访问间隔稍长(比如秒杀后流量回落),就可能被误淘汰 - 它和缓存击穿的防护逻辑(如互斥锁)是正交的:锁只在「查不到缓存」时生效,而提前淘汰让“查不到”发生得更频繁、更不可预期
- 真正适合热点数据的淘汰策略其实是
allkeys-lfu或干脆禁用淘汰(noeviction),配合逻辑过期
allkeys-random 会让缓存穿透后果更严重
当启用 allkeys-random 且业务大量使用空值缓存(redis.set("user:999999", "null", 300))时,这些空值可能被随机淘汰。后续再有相同非法 key 请求,就会再次穿透到 DB——相当于空值缓存形同虚设。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 空值缓存本意是“挡一次,保五分钟”,但
allkeys-random把它变成“挡一次,保不定多久” - 更稳妥的做法是:对空值 key 显式设置较短 TTL,并搭配
volatile-lru或volatile-ttl,确保空值只在过期后才被淘汰 - 布隆过滤器不受淘汰策略影响,所以高风险场景(如用户 ID 校验)应优先用
BloomFilter做前置过滤,而不是依赖空值缓存
noeviction 策略下,缓存雪崩反而可能触发穿透
noeviction 看似安全(写失败也不删数据),但一旦内存满,新 key 写不进 Redis,SET 返回 (error) OOM command not allowed when used memory > 'maxmemory'.。这时如果业务没处理这个错误,就可能跳过缓存直连 DB——尤其在批量预热或突发写入时。
- 这不是穿透的定义(因为 key 是合法的),但效果等价:缓存层失效 + DB 承压
- 关键点在于:很多 SDK 对
OOM错误默认重试或降级逻辑缺失,导致请求静默 fallback 到数据库 - 线上必须监控
evicted_keys和rejected_connections指标;noeviction只适合写极少、读极多且内存预算绝对充足的场景
真正容易被忽略的是:淘汰策略和过期机制不是独立开关,而是协同生效的双刃剑。比如一个 key 同时满足「TTL 剩余 10s」+「LFU 计数最低」+「内存超限」,Redis 会按策略优先级决定先淘汰谁——而这个优先级文档里没明说,只能靠 INFO memory 观察实际行为。










