谈谈 Redis 的内存淘汰策略?
2026年01月01日
一则或许对你有用的小广告
欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于
Spring AI + Spring Boot3.x + JDK 21..., 点击查看; - 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot3.x + JDK 17..., 点击查看项目介绍; 演示链接: http://116.62.199.48:7070/; - 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/
Redis 的内存淘汰策略?
面试考察点
面试官问出这个问题,通常想考察以下几个核心点:
- 对缓存系统核心机制的理解:考察你是否理解当缓存内存用尽时,系统如何处理写入请求这一关键问题。
- 对具体策略的掌握程度:不仅仅是背诵策略名称,更是想知道你能否清晰阐述每种策略的定义、工作原理及区别。
- 技术选型与场景结合的能力:面试官最想听到的是,你能根据不同的业务场景和数据访问模式,分析并选择最合适的淘汰策略。
- 实践与配置经验:你是否了解这些策略在 Redis 中如何配置,以及在实际生产环境中的注意事项。
- 延伸思考能力:能否将 Redis 的内存淘汰与 JVM 垃圾回收或其他系统的缓存策略进行类比或区分,体现知识的广度。
核心答案
当 Redis 所使用的内存达到 maxmemory 配置的阈值时,便会触发内存淘汰。Redis 提供了 8 种策略,可通过 maxmemory-policy 配置,主要分为三类:
- 不淘汰:
noeviction:默认策略。不淘汰任何键,当内存不足时,新写入操作会报错。
- 在所有键中淘汰 (
allkeys-*):allkeys-lru:从所有键中,淘汰最近最少使用的键。allkeys-lfu:从所有键中,淘汰最不经常使用的键。allkeys-random:从所有键中,随机淘汰。
- 在设置了过期时间的键中淘汰 (
volatile-*):volatile-lru:从设置了过期时间的键中,淘汰最近最少使用的键。volatile-lfu:从设置了过期时间的键中,淘汰最不经常使用的键。volatile-random:从设置了过期时间的键中,随机淘汰。volatile-ttl:从设置了过期时间的键中,淘汰剩余生存时间最短的键。
深度解析
原理/机制
- LRU(最近最少使用):传统 LRU 需要维护一个链表,移动开销大。Redis 采用了一种近似 LRU 算法,通过随机采样(默认5个键)并淘汰其中最久未使用的,在性能和精度上取得了平衡。
- LFU(最不经常使用):从 Redis 4.0 开始引入。LFU 会统计每个键的访问频率,并优先淘汰频率最低的键。为了避免早期的高频访问记录永久影响,Redis 的 LFU 实现了访问次数衰减机制,随着时间的推移,计数会逐渐减少。
- TTL(生存时间):这个策略非常直接,它认为即将过期的数据价值更低,应优先被清理。
对比分析与最佳实践
选择哪种策略,完全取决于你的数据特征和业务场景:
| 策略 | 适用场景 | 注意事项 |
|---|---|---|
noeviction | 数据绝对不能丢失,且你能确保内存永远够用(或通过其他方式扩容)。 | 生产环境慎用,除非有完善的监控和告警,否则易导致写入失败,服务不可用。 |
allkeys-lru | 最常用。业务数据访问符合“二八法则”,即部分热点数据被频繁访问。 | 如果你的数据没有明显的冷热区分,效果可能不理想。 |
allkeys-lfu | 访问频率的差异比访问时间的远近更能区分数据价值。例如,某键一天内被短时间密集访问后永不再用,LFU 比 LRU 能更快地将其淘汰。 | 适用于对长期热点和短期爆点的区分有要求的场景。 |
volatile-lru/ttl | 系统中同时存在永久数据和缓存数据。你只想淘汰缓存数据(设置了 TTL 的),而永久数据必须保留。 | 必须为缓存数据正确设置过期时间,否则它们永远不会被纳入淘汰范围,可能导致内存堆积。 |
allkeys-random | 所有键被访问的概率几乎相等,没有明显热点。 | 淘汰最不可控,通常不作为首选。 |
volatile-lfu | 在设置了 TTL 的缓存数据中,需要根据访问频率来淘汰。 | 同 volatile-lru,需确保缓存数据有 TTL。 |
常见误区
- 认为
volatile-*策略只淘汰“已过期”的键:错。它淘汰的是设置了过期时间且未过期的键。过期键的清理是 Redis 的定期删除和惰性删除机制负责的,与内存淘汰是两回事。 - 混淆 LRU 和 LFU:LRU 关注“何时访问”,淘汰 “最老” 的访问记录;LFU 关注 “访问次数”,淘汰 “最不活跃” 的键。一个很久前被访问多次的键,在 LRU 看来可能很 “冷”,但在 LFU 看来可能依然很 “热”。
- 忘记设置
maxmemory:如果不设置最大内存,Redis 将不会触发内存淘汰,直到耗尽所有系统内存,可能引发 OOM 导致进程被杀。
总结
Redis 的内存淘汰策略是一套精细的内存管理工具,核心思想是在内存受限时,根据不同的数据价值评估算法(如 LRU、LFU、TTL)来做出取舍,没有最好的策略,只有最适合业务场景的策略。通常,allkeys-lru 是一个稳健的通用选择。