文章目录

Redis内存淘汰策略LRU和LFU的区别与配置

发布于 2026-05-01 00:16:57 · 浏览 8 次 · 评论 0 条

Redis内存淘汰策略LRU和LFU的区别与配置

当 Redis 使用的内存大小达到配置的上限(maxmemory)时,为了继续提供服务,它必须执行内存淘汰策略,即删除部分已有的键值对以释放内存空间。LRU(Least Recently Used)和 LFU(Least Frequently Used)是其中最核心的两种算法。理解它们的区别并正确配置,是保证 Redis 高性能运行的关键。

LRU 与 LFU 的核心区别

LRU 和 LFU 的根本区别在于判断“谁该被删除”的维度不同:一个是基于“时间”,一个是基于“频率”。

1. LRU (Least Recently Used) 算法

LRU 算法的核心思想是:如果一个数据最近没有被访问过,那么将来被访问的概率也很低。

  • 淘汰依据:最后一次访问的时间。
  • 操作逻辑:当内存不足时,优先淘汰最久没有被访问过的键。
  • 适用场景:适合“热点数据”随时间变化比较明显的业务。例如,新闻资讯网站,大家都在看突发新闻(此时它是热点),过几个小时没人看了(变冷),就应该被淘汰。

2. LFU (Least Frequently Used) 算法

LFU 算法的核心思想是:如果一个数据在过去的访问频率很低,那么将来被访问的概率也很低。

  • 淘汰依据:历史访问的频率(次数)。
  • 操作逻辑:当内存不足时,优先淘汰访问频率最低的键。
  • 适用场景:适合“高频数据”长期稳定的业务。例如,某些基础配置数据或字典类接口,这些数据一旦被加载,会被反复调用,且短时间内不会变冷。

Redis 中的实现细节(近似算法)

为了保证高性能,Redis 并没有使用完美的 LRU 或 LFU 算法,因为完美的算法需要消耗大量的内存来维护复杂的结构。Redis 使用的是近似算法

1. Redis 的 LRU 实现机制

Redis 并不会为所有键维护一个全局的精确链表。它采用了一种随机采样的策略:

  1. 配置采样参数:Redis 配置文件中有一个参数 maxmemory-samples,默认值通常是 5。
  2. 随机选取:当需要淘汰数据时,Redis 会从所有键中随机选取 N 个(即 maxmemory-samples 的值)键。
  3. 比较淘汰:在这 N 个键中,淘汰掉最久没有被访问的那个键。

2. Redis 的 LFU 实现机制

Redis 4.0 之后引入了 LFU 策略。为了更智能地反映访问热度,Redis 使用了一个名为 Morris Counter 的概率计数器,并且引入了“衰减”机制:

  • 计数器:每个键维护一个计数器,每次访问计数器增加,但增加的幅度是随机的(访问次数越多,增加的概率越大)。
  • 衰减因子:如果这个键很久没被访问,Redis 会通过一个公式降低它的计数值(类似“冷却”),防止很久以前的冷数据因为积累了历史点击量而一直占用内存。

LRU 与 LFU 对比总结

下表总结了两种策略在不同维度下的特性:

特性 LRU (Least Recently Used) LFU (Least Frequently Used)
判断标准 距离上一次访问的时间长短 历史访问的总次数
核心逻辑 淘汰“最久”没用的 淘汰“最少”被用的
对突发流量的处理 敏感:突发的读取会让该键变为热点,不被淘汰 不敏感:突发读取不会立即让计数值超过老的热点数据
适用场景 周期性访问、时间相关性强的数据 高频稳定访问、需要过滤偶发性访问的数据
计算开销 极低 较低(略高于 LRU,需维护计数器)

内存淘汰策略配置步骤

Redis 提供了多种具体的策略配置,它们通常分为针对所有键(allkeys)和仅针对设置了过期时间的键(volatile)两类。以下是配置和修改的详细步骤。

第一步:修改配置文件(永久生效)

这是最稳妥的配置方式,修改后重启 Redis 依然有效。

  1. 打开 Redis 的配置文件 redis.conf

  2. 搜索 并找到 maxmemory 配置项。

  3. 取消注释 并设置最大内存限制(例如设置为 1GB)。

    maxmemory 1gb
  4. 搜索 并找到 maxmemory-policy 配置项。

  5. 取消注释 并将其设置为你需要的策略值。

    常用的策略值包括:

    • noeviction:默认策略,内存满时不删除,直接报错。
    • allkeys-lru:对所有键使用 LRU 淘汰。
    • volatile-lru:仅在设置了过期时间的键中使用 LRU 淘汰。
    • allkeys-lfu:对所有键使用 LFU 淘汰(Redis 4.0+)。
    • volatile-lfu:仅在设置了过期时间的键中使用 LFU 淘汰(Redis 4.0+)。
    • allkeys-random:对所有键随机淘汰。
    • volatile-random:在设置了过期时间的键中随机淘汰。
    • volatile-ttl:淘汰剩余生存时间(TTL)最短的键。

    例如,配置为对所有键使用 LRU:

    maxmemory-policy allkeys-lru
  6. 保存 配置文件。

  7. 重启 Redis 服务使配置生效。

第二步:使用命令行动态配置(无需重启)

如果你不想重启服务,或者想临时测试策略,可以使用 redis-cli 连接到服务器进行动态修改。

  1. 连接 到 Redis 服务。
    redis-cli
  2. 设置 最大内存(如果尚未设置)。
    CONFIG SET maxmemory 1gb
  3. 设置 淘汰策略。
    例如,切换到 LFU 模式:
    CONFIG SET maxmemory-policy allkeys-lfu
  4. 验证 配置是否成功。
    CONFIG GET maxmemory-policy

    输出结果应包含 allkeys-lfu


如何调整 LRU/LFU 的精度

如果你发现 Redis 的淘汰效果不够理想(例如该保留的热点数据被误删了),可以通过调整采样数量来提高算法的精确度,但会增加少许 CPU 消耗。

  1. 编辑 redis.conf 文件。

  2. 找到 maxmemory-samples 配置项。

  3. 修改 数值。默认值为 5,建议范围是 5 到 10。值越大,结果越接近完美的 LRU/LFU,但 CPU 消耗也越高。

    例如,设置为 10:

    maxmemory-samples 10
  4. 保存重启 Redis,或者使用命令:

    CONFIG SET maxmemory-samples 10

实战中的策略选择建议

在实际生产环境中,选择哪种策略取决于你的数据访问模式:

  1. 如果你的数据主要是缓存数据,且没有设置过期时间
    建议使用 allkeys-lru。这是最通用的策略,能有效保留最近被访问的数据。

  2. 如果你的数据主要是缓存数据,但存在某些极其频繁访问的“钉子户”数据
    建议使用 allkeys-lfu。它能有效过滤掉偶尔被访问一次的“噪音”数据,保留真正的高频核心数据。

  3. 如果你主要希望缓存某些带过期时间的会话或临时数据
    建议使用 volatile-lruvolatile-lfu。这可以确保未设置过期时间的永久数据不会被意外删除,仅利用空闲内存来缓存临时数据。

  4. 如果是做简单的缓存,不希望复杂的逻辑
    使用默认的 noeviction 配合合理的过期时间策略,或者直接使用 allkeys-random(在数据集较小且访问均匀时效果尚可)。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文