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 过期清理的核心机制,其执行逻辑如下:
- 从设置了过期时间的 key 集合中随机选取 20 个 key。
- 检查这 20 个 key 中已过期的比例。
- 如果过期比例超过 25%,则重复步骤 1-2;否则等待下一次定期循环。
- 每次定期删除的总耗时默认不超过 25ms,防止阻塞主线程。
避坑提示:当大量 key 在同一秒内过期(例如缓存批量失效),定期删除可能无法及时清理所有过期 key。此时惰性删除作为兜底,但若这些 key 在过期后不再被访问,它们将持续占用内存直到内存淘汰触发。建议对缓存 TTL 添加随机偏移量(如
TTL + random(0, 300) 秒),避免雪崩式过期。
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 计数器 + 衰减因子) |
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 计数器衰减时间(分钟)