Redis 缓存淘汰策略(LRU/LFU/TTL)
候选人小孙在美团的一面中,面试官问道:
"Redis 内存满了怎么办?有哪些淘汰策略?"
小孙说:"有 LRU、LFU...还有按时间过期?"面试官追问:"Redis 4.0 之后的 LRU 和之前有什么区别?"
小李愣了一下,说:"不太记得了..."
面试官继续:"volatile-lru 和 allkeys-lru 有什么区别?"
小孙说:"一个是有过期时间的,一个是没有的?"
面试官点点头,又问:"那 sampling 算法是什么?"
小孙彻底卡住。
【面试官心理】 这道题我用来区分"背概念"和"真正理解淘汰机制"的候选人。知道 LRU/LFU 区别的占 40%,能说清 volatile 和 allkeys 区别的占 30%,能解释 sampling 算法的占 10%。淘汰策略是 Redis 生产环境中的核心配置,选错了轻则性能下降,重则服务崩溃。
一、Redis 内存管理 🔴
1.1 问题拆解
Redis 的内存是有限的,当内存满了之后,新的写入会被拒绝:
1.2 触发淘汰的时机
【面试官心理】 我问他内存满了怎么办,其实是在考察他对 Redis 内存管理机制的理解程度。很多候选人知道 maxmemory,但不知道它是怎么触发的,以及淘汰过程是同步还是异步的。
二、8种淘汰策略 🔴
2.1 策略分类
Redis 6.0 支持 8 种淘汰策略:
2.2 volatile vs allkeys
2.3 LRU vs LFU vs Random vs TTL
【面试官心理】 四种淘汰指标是面试的基础。能说出四种区别的占 50%,能解释 LRU 和 LFU 各自优缺点的占 20%。LFU 是 Redis 4.0 才引入的,很多候选人还在用 LRU。
三、LRU 算法详解 🔴
3.1 朴素 LRU 的问题
如果用标准的 LRU,需要维护一个按访问时间排序的双向链表:
Redis 的问题是:每次访问都需要更新链表,O(n) 复杂度不可接受。
3.2 Redis 的 LRU 实现:近似 LRU
3.3 近似 LRU vs 精确 LRU
记忆口诀:Redis 的 LRU 不是真正的 LRU,是"近似 LRU"。采样 16 个 key,按 LRU 时间排序,淘汰最老的那个。如果 16 个里最好的选择也不够好,可以增大 maxmemory-samples 配置。
3.4 ❌ 错误示范
候选人原话:"Redis 的 LRU 就是把最久没访问的数据淘汰掉。"
问题诊断:
- 不知道 Redis 的 LRU 是"近似"算法
- 不理解采样机制
- 不知道 LRU_BITS 的存储方式
面试官内心 OS:"这个候选人肯定没有看过 Redis 源码,只是在网上扫了一眼 LRU 的概念。"
四、LFU 算法详解 🟡
4.1 LFU vs LRU
4.2 LFU 的衰减机制
如果一个数据曾经很热,但现在很久没访问了,应该被淘汰。LFU 需要衰减:
4.3 LFU 的冷启动问题
新进入 Redis 的 key,访问次数是 0。如果用 LFU,它会在第一批被淘汰——即使它可能是热数据。
解决方案:访问次数不是从 0 开始,而是从一个较高的初始值开始。
【面试官心理】 LFU 是 Redis 4.0 的新特性。能说出 LFU 和 LRU 区别的占 20%,能解释衰减机制的占 5%,能说出冷启动问题的占 3%。LFU 是一个更"聪明"的淘汰策略,但在某些场景下可能不如 LRU。
五、生产选型 🔴
5.1 场景一:纯缓存,TTL 统一
为什么不用 allkeys-lru? 因为所有 key 都有 TTL,volatile-lru 只会淘汰有 TTL 的 key,不会误删永久数据。
5.2 场景二:缓存 + 永久数据混合
5.3 场景三:超高热点数据
5.4 场景四:不允许丢失任何数据
【面试官心理】 生产选型是淘汰策略最核心的考点。能说出不同场景选不同策略的占 30%,能给出具体配置的占 10%。选错淘汰策略可能导致:缓存命中率下降(random)、热点数据被淘汰(LRU 误杀大对象)、数据丢失(noeviction 但内存不足)。
六、生产避坑
:::warning ⚠️ 生产中的三大翻车点:
-
maxmemory 设置过小:Redis 作为缓存时,内存逐渐增长,最终达到 maxmemory,大量请求被 OOM 拒绝。解决方案:监控
used_memory_human和maxmemory_human,设置告警。 -
淘汰策略选错:用 allkeys-random 导致热点数据被淘汰,命中率骤降。解决方案:分析业务数据的访问模式,选择合适的淘汰策略。
-
maxmemory-samples 过大:采样数过大(如 100),导致淘汰过程消耗过多 CPU。解决方案:默认 5 即可,高内存压力时可调大。 :::
排查方法:
:::tip 💡 生产最佳实践:
- 预估数据量:总数据量 / 0.7 = 所需 maxmemory(考虑 30% 内存碎片和 overhead)
- 监控指标:
evicted_keys > 0→ 说明淘汰策略在工作了,可能需要扩容 - LRU vs LFU:业务有明确热点的用 LFU,数据分布均匀的用 LRU
- maxmemory-samples:默认 5,数据量大且淘汰频繁时可调大到 10
- 淘汰过程是同步的,会阻塞主线程! :::
【面试官心理】 这道题我想最终验证的是候选人的"生产经验"。能把 8 种淘汰策略背出来的占 40%,能解释 LRU 采样算法的占 20%,能在生产环境中正确选型的占 10%。淘汰策略选错了轻则性能下降,重则 OOM 导致服务不可用,这是一个需要认真对待的配置项。