当前位置: 首页 > news >正文

详解Redis的内存淘汰策略

        Redis 的内存淘汰策略是当 Redis 的内存使用量达到配置的上限时,系统会根据预设的规则自动选择并删除一些键,以释放内存空间。Redis 提供了多种内存淘汰策略,每种策略都有其特定的适用场景和行为。

1. 不淘汰策略 (报错)

1.1 noeviction (默认策略):

  • 行为: 当内存不足时,所有会申请更多内存的命令(如 SETLPUSHSADD 等)都将返回错误(通常是 (error) OOM command not allowed when used memory > 'maxmemory')。

  • 适用场景: 数据绝对不能丢失,且开发者确信应用逻辑能处理内存不足错误(例如:优雅降级、清理逻辑、水平扩展)。生产环境使用需非常谨慎。

2.淘汰策略 - 在设置了过期时间的键中筛选

2.1 volatile-lru (Least Recently Used):

  • 行为: 从设置了过期时间 (EXPIRE/TTL) 的键中,淘汰最近最少使用的键。

  • 原理: 近似 LRU 算法(Redis 使用采样而非完全精确 LRU 以节省内存和 CPU)。

2.2 volatile-lfu (Least Frequently Used) (Redis 4.0+):

  • 行为: 从设置了过期时间的键中,淘汰访问频率最低的键。

  • 原理: 近似 LFU 算法,通过计数器和衰减机制估算访问频率。对突发访问后长期不用的键淘汰效果更好。

2.3 volatile-ttl (Time To Live):

  • 行为: 从设置了过期时间的键中,淘汰剩余生存时间 (TTL) 最短的键。

  • 原理: 优先移除即将过期的键,腾出空间给新键。适用于缓存场景,确保新缓存有空间。

2.4 volatile-random:

  • 行为: 从设置了过期时间的键中,随机淘汰一个键。

  • 原理: 简单随机选择。效率高但淘汰可能不合理。

3. 淘汰策略 - 在所有键中筛选:

3.1 allkeys-lru:

  • 行为: 从所有键(无论是否设置过期时间)中,淘汰最近最少使用的键。

  • 原理: 近似 LRU。适用于希望将 Redis 用作缓存的场景,认为所有数据都可被淘汰。

3.2 allkeys-lfu (Redis 4.0+):

  • 行为: 从所有键中,淘汰访问频率最低的键。

  • 原理: 近似 LFU。同样适用于纯缓存场景,且能更好地淘汰长期冷门数据。

3.3 allkeys-random:

  • 行为: 从所有键中,随机淘汰一个键。

  • 原理: 简单随机选择。效率最高但淘汰最不可控。

4. 关键机制详解

  • 近似算法 (Approximated Algorithms):

    • Redis 的 lru 和 lfu 都是近似实现,并非严格精确。这是为了在性能和内存消耗上取得平衡。

    • LRU 近似: Redis 维护一个候选池(默认大小 16),每次淘汰时从池中(而非全量数据)挑选最老的淘汰。新访问的键只有其“年龄”比池中最老的键还老时才会进入候选池。可通过 maxmemory-samples 配置候选池大小(增加提高精度但降低性能)。

    • LFU 近似: 使用 Morris 计数器(概率递增)和一个衰减时间(lfu-decay-time)来模拟访问频率。计数器值会随时间衰减,避免早期访问的键长期占据优势。通过 lfu-log-factor 控制计数器增长难度。

  • LFU vs LRU:

    • LRU: 只关心最近一次访问时间。一个过去访问频繁但现在冷门的键可能比一个新近访问但频率低的键更易被保留。

    • LFU: 关心整个生命周期内的访问频率。能更好地识别并保留真正的热点数据,即使它们最近没被访问(但历史上访问非常多),而淘汰那些偶尔访问或曾经热过但已过气的数据。更适合识别长期热点。

  • volatile-* vs allkeys-*:

    • volatile-*: 只淘汰有 TTL 的键。意味着没有设置过期时间的键永远不会被自动淘汰。如果这类键很多或很大,即使淘汰了所有过期键也可能无法释放足够内存,最终导致 noeviction 行为或 OOM。适用于有明确生命周期的缓存数据,同时存在不应丢失的永久数据。

    • allkeys-*: 所有键都是候选对象。没有设置过期时间的键也可能被淘汰。适用于纯缓存场景,所有数据都可以在需要时重新生成或从源头获取。

5. 如何选择策略?

  • 数据容忍度:

    • 数据绝对不能丢? -> noeviction (需确保有处理 OOM 的能力或足够内存)。

    • 所有数据都可重建? -> allkeys-lru 或 allkeys-lfu (推荐,最安全,避免永久键占满内存)。

    • 部分数据可丢(缓存),部分不能丢? -> volatile-* (需确保永久键有足够空间,否则仍可能 OOM)。

  • 访问模式:

    • 有明显热点数据? -> allkeys-lru / volatile-lru

    • 访问模式相对均匀,或需要淘汰长期冷门数据? -> allkeys-lfu / volatile-lfu (Redis 4.0+ 推荐)。

    • 访问模式完全随机或无关紧要? -> allkeys-random / volatile-random (效率最高)。

  • 数据过期特征:

    • 缓存项有明确且合理的 TTL? -> volatile-ttl 是一种高效选择,优先淘汰快过期的。

    • TTL 分布不均匀或没有意义? -> 避免 volatile-ttl

6. 总结与建议

  • 生产环境强烈推荐使用 allkeys-lru 或 allkeys-lfu (Redis 4.0+),除非有非常明确的理由不这么做。 这避免了未设置过期时间的键导致内存无法释放的风险。

  • allkeys-lfu 通常比 allkeys-lru 更能精准保留真正的热点数据。 如果使用 Redis 4.0 或更高版本,allkeys-lfu 是纯缓存场景的首选。

  • 谨慎使用 volatile-* 策略。必须确保永久键(未设置 TTL)的总大小远小于 maxmemory,并留出足够缓冲给缓存键,否则仍有 OOM 风险。

  • noeviction 仅适用于数据绝对不能丢失且应用能完美处理 OOM 错误的场景。大多数缓存场景不适用。

  • volatile-ttl 在缓存数据 TTL 设置合理且分布良好时效率很高。

  • 随机策略 (*-random) 效率最高但淘汰最不可控,一般只在其他策略效果不佳且性能压力极大时考虑。

  • 根据实际情况调整 maxmemory-samples (LRU/LFU 精度) 和 lfu-log-factor/lfu-decay-time (LFU 行为)。

http://www.lryc.cn/news/573037.html

相关文章:

  • HCIP-华为VRP系统基础
  • Linux——库文件生成和使用
  • 软件架构的发展历程——从早期的单体架构到如今的云原生与智能架构
  • 初学python的我开始Leetcode题10-2
  • RPC常见问题回答
  • 【Go语言基础】对齐边界与内存填充
  • HTTP 请求方法与状态码
  • 深入解析:如何实时获取Socket接收缓冲区的数据量
  • Cesium、ThreeWebGL详解(二)渲染引擎向GPU传数据、性能优化、引擎对比
  • C++ 学习笔记精要(二)
  • mysql server层做了什么
  • Spring 的IoC 和 AOP
  • 博士,超28岁,出局!
  • 算法第38天|322.零钱兑换\139. 单词拆分
  • moments_object_model_3d这么理解
  • 信安实验室CTF writeup
  • 【Python进阶系列】第10篇:Python 项目的结构设计与目录规范 —— 从脚本到模块,从混乱到整洁
  • 电力企业数字化——解读44页电力集团战略实施和集团对标一体化指标体系框架【附全文阅读】
  • 计算机——硬盘驱动器
  • 【大模型lora微调】关于推理时如何使用 LoRA Adapter
  • 如何填写“appium inspector”内容?
  • 数据分析和可视化:Py爬虫-XPath解析章节要点总结
  • 第32周———Tensorflow|LSTM-火灾温度预测
  • HTML一键打包EXE串口API介绍
  • 智能群跃小助手发布说明
  • 【编译原理】语句的翻译
  • 二分查找----1.搜索插入位置
  • 【LLM06---相对位置编码】
  • 下载链接记录
  • Linux 内核同步管理全解:原理 + 实战 + 考点