3. Redis 过期策略与内存淘汰:TTL 设置、惰性删除、定期删除、LRU/LFU 淘汰机制对缓存的影响
在缓存闭环中,数据何时失效、内存何时释放,直接决定了缓存命中率与系统稳定性。Redis 采用“被动过期 + 主动清理 + 内存淘汰”三层防御体系。理解这三层的协作关系,是设计高可用缓存边界的关键。
3.1 TTL 设置:过期时间的源头
所有过期行为都始于 EXPIRE、PEXPIRE、EXPIREAT 或 SETEX 命令。Redis 在每个键的 redisObject 中记录 expire 字段(毫秒级时间戳)。
| 命令 | 精度 | 典型场景 |
|---|---|---|
EXPIRE key seconds |
秒 | 通用缓存 TTL |
PEXPIRE key ms |
毫秒 | 高精度限流窗口 |
EXPIREAT key timestamp |
秒时间戳 | 固定时刻失效(如每日 0 点) |
SETEX key seconds value |
秒 | 原子写入+过期 |
避坑提示: 对已有 TTL 的键再次执行
EXPIRE 会覆盖原过期时间。使用 TTL key 返回 -2 表示键不存在,-1 表示未设置过期。
3.2 惰性删除:被动防御
当客户端访问一个键时,Redis 会先检查该键是否已过期。如果过期,立即删除并返回 nil。这种策略称为 惰性删除。
- 优点: CPU 开销极低,只在实际访问时检查。
- 缺点: 过期键如果一直不被访问,会长期占用内存,形成“内存泄漏”。
惰性删除是 Redis 过期策略的第一道防线,但仅靠它远远不够。
3.3 定期删除:主动清理
为了解决惰性删除的内存残留问题,Redis 每隔 100ms 执行一次 定期删除 任务。其核心逻辑如下:
- 从
expires字典中随机选取 20 个键。 - 删除其中已过期的键。
- 如果过期比例超过 25%,重复步骤 1-2。
- 每次执行总耗时不超过 25ms,避免阻塞主线程。
关键参数:
ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP:默认 20,每次采样数。ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC:默认 25,CPU 时间占比。
定期删除是第二道防线,它保证了过期键不会无限堆积。
3.4 内存淘汰:最后一道防线
当内存使用达到 maxmemory 上限时,Redis 必须主动淘汰键来释放空间。淘汰策略通过 maxmemory-policy 配置。
| 策略 | 含义 | 适用场景 |
|---|---|---|
noeviction |
不淘汰,写入直接报错 | 禁止丢失数据的场景 |
allkeys-lru |
全键 LRU 淘汰 | 通用缓存,无优先级区分 |
volatile-lru |
仅淘汰设置了 TTL 的键 | 缓存+持久化混合使用 |
allkeys-lfu |
全键 LFU 淘汰 | 访问频率差异明显的场景 |
volatile-lfu |
仅淘汰设置了 TTL 的键 | 热点数据保护 |
allkeys-random |
全键随机淘汰 | 均匀分布,无热点 |
volatile-ttl |
淘汰剩余 TTL 最短的键 | 优先清理即将过期的数据 |
3.5 LRU 与 LFU 淘汰机制对比
LRU(Least Recently Used)和 LFU(Least Frequently Used)是两种最常用的淘汰算法。Redis 对它们做了近似实现以节省内存。
3.6 三层防御协作流程
当一个键到达过期时间或被内存淘汰时,Redis 的完整处理流程如下:
3.7 对缓存闭环的影响
缓存雪崩风险: 大量键在同一时间过期,会导致缓存瞬间空洞,请求全部穿透到后端。解决方案:TTL 添加随机偏移(±10%~20%),或使用
EXPIREAT 分散过期时间。
- 缓存击穿: 热点键过期瞬间,高并发请求直接打到数据库。使用互斥锁或逻辑过期(不设物理 TTL,由业务层控制)来防护。
- 缓存穿透: 查询一个不存在的键,每次都会穿透。布隆过滤器 + 空值缓存(短 TTL)是标准解法。
- 淘汰策略选择: 缓存层推荐
allkeys-lru;持久化层推荐volatile-lru或noeviction;热点数据隔离层推荐volatile-lfu。
3.8 实战配置建议
# redis.conf 关键配置
maxmemory 4gb
maxmemory-policy allkeys-lru
# 定期删除 CPU 占比
active-expire-effort 1 # 1-10,默认 1,越大越积极
# 惰性删除开关(默认开启)
lazyfree-lazy-expire yes
lazyfree-lazy-eviction yes
监控命令:
INFO stats查看expired_keys、evicted_keys指标。MEMORY STATS查看内存分配与碎片率。OBJECT idletime key查看键的空闲时间(LRU 决策依据)。