3. Redis 过期策略与内存淘汰机制

在搜索缓存闭环中,缓存数据不可能永久驻留。Redis 作为高性能缓存层,必须通过过期策略清理失效数据,并通过内存淘汰机制在内存耗尽时做出取舍。理解这两套机制的原理与适用场景,是保障缓存一致性与系统稳定性的核心前提。

3.1 三种过期删除策略

Redis 对设置了 TTL(生存时间)的 key,采用以下三种策略配合完成过期删除:

策略名称 触发时机 CPU 开销 内存回收及时性 主要风险
定时删除 创建 key 时启动定时器 高(每个过期 key 一个定时器) 立即回收 大量 key 同时过期时 CPU 压力极大
惰性删除 每次访问 key 时检查 低(仅访问时触发) 延迟回收(可能堆积) 过期 key 长期占用内存
定期删除 Redis 主循环周期性执行 可控(可配置频率与耗时) 折中回收 参数配置不当可能回收不及时或 CPU 抖动
生产实践:Redis 默认采用惰性删除 + 定期删除的组合策略。定时删除因 CPU 开销过高,在实际版本中并未默认启用。定期删除由 redis.conf 中的 hz 参数控制(默认 10),表示每秒执行 10 次过期扫描。

3.2 定期删除的执行流程

定期删除是 Redis 过期清理的核心机制,其执行逻辑如下:

  1. 从设置了过期时间的 key 集合中随机选取 20 个 key。
  2. 检查这 20 个 key 中已过期的比例。
  3. 如果过期比例超过 25%,则重复步骤 1-2;否则等待下一次定期循环。
  4. 每次定期删除的总耗时默认不超过 25ms,防止阻塞主线程。
避坑提示:当大量 key 在同一秒内过期(例如缓存批量失效),定期删除可能无法及时清理所有过期 key。此时惰性删除作为兜底,但若这些 key 在过期后不再被访问,它们将持续占用内存直到内存淘汰触发。建议对缓存 TTL 添加随机偏移量(如 TTL + random(0, 300) 秒),避免雪崩式过期。
Redis 过期删除策略组合工作流程 定时删除 (默认禁用) 定期删除 (hz 参数控制) 惰性删除 (访问时检查) 替代 兜底 随机采样 20 个过期 key 检查过期比例 比例 > 25% ? 是 继续采样 否 等待下次循环 说明:定期删除每次执行耗时不超过 25ms,防止阻塞 Redis 主线程

3.3 内存淘汰机制

当 Redis 内存使用量达到 maxmemory 限制时,系统必须根据配置的淘汰策略删除部分 key 以释放空间。Redis 8 种淘汰策略可分为三大类:

类别 策略名称 淘汰依据 适用场景
不淘汰 noeviction 不淘汰任何 key,写入操作直接返回错误 纯内存数据库,不允许数据丢失
(生产环境极少使用,会导致写入失败)
全体 key 淘汰 allkeys-lru 最近最少使用(LRU) 搜索缓存、热点数据缓存
allkeys-lfu 最不经常使用(LFU) 访问频率差异明显的场景
allkeys-random 随机淘汰 数据访问均匀,无热点
设置了 TTL 的 key 淘汰 volatile-lru 在过期 key 中淘汰最近最少使用 混合存储(部分持久化 + 部分缓存)
volatile-lfu 在过期 key 中淘汰最不经常使用 带 TTL 的热点数据
volatile-ttl 淘汰剩余 TTL 最短的 key 优先保留即将过期的数据
特殊 volatile-random 在过期 key 中随机淘汰 TTL 数据分布均匀
推荐配置:对于搜索缓存场景,建议使用 allkeys-lru 策略。它不区分 key 是否设置 TTL,统一按最近访问时间淘汰,能最大化缓存命中率。配置方式:maxmemory-policy allkeys-lru。

3.4 LRU 与 LFU 的核心差异

LRU 和 LFU 是生产中最常用的两种淘汰算法,理解其差异对缓存一致性设计至关重要:

对比维度 LRU(最近最少使用) LFU(最不经常使用)
淘汰依据 最后一次访问时间 一段时间内的访问频率
内存开销 低(仅记录访问时间戳) 较高(需维护访问计数器)
抗突发访问 弱(一次突发访问可让冷数据长期驻留) 强(频率累积,突发访问影响有限)
适用场景 热点数据随时间漂移 访问模式长期稳定
Redis 实现 近似 LRU(采样 5 个 key 淘汰最旧的) 近似 LFU(Morris 计数器 + 衰减因子)
LRU vs LFU 淘汰逻辑对比 LRU 淘汰逻辑 Key A(最近访问) Key B Key C(最久未访问) 淘汰 释放内存 LFU 淘汰逻辑 Key X 访问频率:100 Key Y 访问频率:50 Key Z 访问频率:3 淘汰 释放内存 LRU 关注“最近是否被访问”;LFU 关注“历史上是否经常被访问”

3.5 缓存一致性视角下的策略选择

在搜索缓存闭环中,过期策略与淘汰机制直接影响缓存与数据库之间的数据一致性:

  • 过期时间设置:搜索缓存建议设置 TTL(如 600-3600 秒),配合惰性删除 + 定期删除,确保数据最终一致性。
  • 淘汰策略选择:推荐 allkeys-lru,避免因 TTL 设置不当导致缓存雪崩。
  • 内存水位监控:通过 INFO memory 命令监控 used_memory 与 maxmemory 比例,当使用率超过 80% 时预警。
  • 淘汰对一致性的影响:被淘汰的 key 会导致下次查询穿透到数据库,需配合缓存预热或主动更新策略。
生产配置示例:
# redis.conf 关键配置
maxmemory 4gb
maxmemory-policy allkeys-lru
maxmemory-samples 10          # LRU/LFU 采样数,越大越精确,CPU 开销越高
hz 10                         # 定期删除频率
lfu-log-factor 10             # LFU 计数器增长因子
lfu-decay-time 1              # LFU 计数器衰减时间(分钟)