【🔥🔥🔥Redis 内存管理核心】过期键删除策略与内存淘汰机制详解

【🔥🔥🔥Redis 内存管理核心】过期键删除策略与内存淘汰机制详解

    正在检查是否收录...
一言准备中...

【🔥🔥🔥Redis 内存管理核心】过期键删除策略与内存淘汰机制详解

Redis 的

过期键删除策略

内存淘汰策略

是其管理内存、防止内存耗尽的关键机制,它们解决的是不同层面的问题:

一、过期键删除策略

目标是

自动删除那些设置了过期时间且已过期的键

,释放其占用的内存。Redis 采用两种策略协同工作:

  1. 惰性删除

    • 原理:

      当客户端尝试

      访问

      一个键时,Redis 会先检查这个键是否设置了过期时间以及是否已过期。
    • 操作:

      如果键已过期,Redis 会立即删除这个键,然后才执行客户端的访问命令(返回 nil 或执行失败)。
    • 优点:

      对 CPU 时间友好。只有在真正访问到过期键时才付出删除的成本。没有访问的过期键即使存在,也不会消耗额外的 CPU 去删除它们。
    • 缺点:

      对内存不友好。如果一个键设置了过期时间但之后再也没有被访问过,那么它会一直占用内存空间,直到被访问或者被定期删除策略扫描到并删除。这相当于一种“内存泄漏”。
  2. 定期删除

    • 原理:

      Redis 会

      周期性地、主动地

      从设置了过期时间的键集合中

      随机抽取

      一部分键(默认每次检查 20 个键),检查它们是否过期。
    • 操作:

      • 每次执行时,从过期字典中随机选择一定数量的键。
      • 删除其中所有已过期的键。
      • 如果发现本次检查中过期的键比例超过一定阈值(默认是 25%),则

        立即再随机抽取一批

        键进行检查(循环),直到过期键比例降到阈值以下或达到时间限制(避免过度占用 CPU)。
    • 优点:

      一定程度上减少了惰性删除带来的内存浪费问题,通过周期性扫描清理掉那些长期不被访问的过期键。
    • 缺点:

      需要平衡扫描的频率、每次扫描的数量以及 CPU 消耗。扫描太频繁或每次扫描太多键会消耗过多 CPU;扫描太少或太慢则可能导致大量过期键堆积。它是一个

      折中方案

      ,无法保证实时删除所有过期键。

总结:

Redis 通过

惰性删除 + 定期删除

的组合策略来管理过期键。惰性删除确保访问时数据是最新的且能释放内存;定期删除则像一个“清洁工”,定期清理那些“僵尸”过期键,减少内存占用。两者互补,但都无法保证绝对实时删除所有过期键。

二、内存淘汰策略

目标是当 Redis 使用的内存

达到 maxmemory 配置的限制

时,Redis 如何选择要删除哪些键(无论是否过期)来释放空间,以便写入新数据。这是防止 Redis 因内存耗尽而崩溃的最后一道防线。

Redis 提供了 8 种内存淘汰策略,通过 maxmemory-policy 配置项指定:

  1. noeviction

    默认策略

    。当内存不足时,新写入操作会

    报错

    (如 (error) OOM command not allowed when used memory > 'maxmemory')。读操作通常不受影响。适用于你确信数据绝对不能丢失且宁愿拒绝写入也不能覆盖数据的场景。
  2. allkeys-lru

    :从

    所有键空间

    中,使用

    LRU 算法

    淘汰最近最少使用的键。这是最常用且通常效果较好的策略。
  3. volatile-lru

    :从

    设置了过期时间的键空间

    中,使用

    LRU 算法

    淘汰最近最少使用的键。
  4. allkeys-lfu

    :从

    所有键空间

    中,使用

    LFU 算法

    淘汰最不经常使用的键(根据访问频率)。适用于访问模式随时间变化较大的场景。
  5. volatile-lfu

    :从

    设置了过期时间的键空间

    中,使用

    LFU 算法

    淘汰最不经常使用的键。
  6. allkeys-random

    :从

    所有键空间

    中,

    随机

    淘汰任意键。
  7. volatile-random

    :从

    设置了过期时间的键空间

    中,

    随机

    淘汰任意键。
  8. volatile-ttl

    :从

    设置了过期时间的键空间

    中,淘汰

    剩余生存时间最短

    的键。即优先淘汰即将过期的键。

关键点说明

  • 作用时机:

    仅当内存使用达到 maxmemory 限制且客户端尝试执行会

    增加内存使用量

    的命令(如 SET, LPUSH, HINCRBY 等)时触发淘汰。
  • 作用范围:

    allkeys- 开头的策略会淘汰所有键(包括未设置过期时间的键)。以 volatile- 开头的策略

    只淘汰设置了过期时间的键

  • volatile-lru/volatile-lfu/volatile-random/volatile-ttl 的特殊情况:

    如果内存不足时,淘汰池(设置了过期时间的键)中

    没有合适的键可淘汰

    (例如没有键设置过期时间),那么这些策略的行为会

    退化成 noeviction

    ,新写入操作会报错。
  • LRU vs LFU:

    • LRU (Least Recently Used):

      关注“最近使用时间”。认为最近没被用过的键将来也不太可能被用到。实现上是近似 LRU(采样)。
    • LFU (Least Frequently Used):

      关注“访问频率”。认为访问次数最少的键将来也不太可能被用到。Redis 实现的 LFU 会随时间衰减访问计数(避免旧热点数据长期霸占)。
  • 选择策略:

    • 如果数据访问模式接近 LRU,或者不确定,allkeys-lru 通常是最佳选择。
    • 如果数据有明显的热点和冷门区分,且热点访问频繁,allkeys-lfu 可能更好。
    • 如果你希望 Redis 只作为缓存使用(数据可丢失),所有键都设置了过期时间,并且希望优先淘汰快过期的数据,可以用 volatile-ttl
    • 如果你有部分持久化数据(不能淘汰)和部分缓存数据(可淘汰),确保缓存数据都设置了过期时间,然后使用 volatile-lruvolatile-lfu
    • noeviction 适用于数据绝对不能丢失的场景(但要做好容量规划和监控)。
    • allkeys-randomvolatile-random 通常效果不如基于 LRU/LFU 的策略,除非你的访问模式是完全随机的。

总结:

内存淘汰策略是 Redis 在内存耗尽时的

应急机制

,用于释放空间以允许新数据写入。你需要根据数据的特性(是否可丢失、访问模式、是否都设过期时间)来谨慎选择合适的策略。allkeys-lruallkeys-lfu 是最常用和推荐的通用策略。务必配置 maxmemory 并根据需要设置 maxmemory-policy



  • 本文作者:WAP站长网
  • 本文链接: https://wapzz.net/post-27001.html
  • 版权声明:本博客所有文章除特别声明外,均默认采用 CC BY-NC-SA 4.0 许可协议。
本站部分内容来源于网络转载,仅供学习交流使用。如涉及版权问题,请及时联系我们,我们将第一时间处理。
文章很赞!支持一下吧 还没有人为TA充电
为TA充电
还没有人为TA充电
0
  • 支付宝打赏
    支付宝扫一扫
  • 微信打赏
    微信扫一扫
感谢支持
文章很赞!支持一下吧
关于作者
2.7W+
9
1
2
WAP站长官方

JavaScript 编年史:探索前端界巨变的幕后推手

上一篇

最后一个小公主@亚特兰贵父 爆火,千篇一律的抽象视频为何让网友上瘾?

下一篇
评论区
内容为空

这一切,似未曾拥有

  • 复制图片
按住ctrl可打开默认菜单