Redis过期淘汰策略深度解析
一、核心策略分类
1.1 过期键处理策略
1.1.1 定期删除(Active Expiration)
- 实现原理:每隔100ms随机抽取20个设置了过期时间的Key进行检查,若过期则删除
- 触发条件:由
serverCron时间事件驱动,每次执行不超过25ms - 优化机制:
- 哈希桶遍历策略:连续扫描空桶超过16次则终止
- 比例控制:单次删除过期Key比例超过25%时提前终止
1.1.2 惰性删除(Lazy Expiration)
- 触发时机:客户端访问Key时检查是否过期
- 实现代码:
// Redis源码dict.c中的过期检查 if (key->type == REDIS_EXPIRE) { if (expireIfNeeded(key)) { return NULL; // 已过期直接返回 } } - 适用场景:冷数据自动清理,避免内存泄漏
1.2 内存淘汰策略
通过maxmemory-policy配置,当内存使用超过maxmemory时生效:
| 策略 | 行为描述 | 适用场景 |
|---|---|---|
| volatile-lru | 从带TTL的Key中淘汰最近最少使用的 | 缓存热点数据 |
| volatile-ttl | 从带TTL的Key中淘汰剩余生存时间最短的 | 优先清理即将过期数据 |
| volatile-random | 从带TTL的Key中随机淘汰 | 无差别淘汰过期数据 |
| allkeys-lru | 从所有Key中淘汰最近最少使用的 | 全量缓存管理 |
| allkeys-random | 从所有Key中随机淘汰 | 无差别清理场景 |
| allkeys-lfu | 从所有Key中淘汰访问频率最低的(Redis 4.0+) | 长尾数据清理 |
| noeviction | 拒绝写入并返回错误 | 数据强一致性要求场景 |
二、LRU/LFU算法实现细节
2.1 LRU近似算法
-
数据结构:每个Key的
lru字段记录最近访问时间戳(24bit,精度1秒) -
淘汰流程:
- 随机抽取
maxmemory-samples个Key(默认5) - 计算空闲时间:
idle_time = (current_time - lru) * resolution - 选择空闲时间最长的Key淘汰
- 随机抽取
-
缺陷:
- 无法精确跟踪所有Key的访问顺序
- 24bit时间戳导致194天后时间回绕
2.2 LFU算法(Redis 4.0+)
-
数据结构:
lru字段低8bit记录访问频率(LFU计数器)- 高16bit记录精确到毫秒的访问时间
-
淘汰逻辑:
// LFU淘汰概率计算 double p = 1.0 / (lfu_counter * server.lfu_log_factor + 1); if (rand() < p) increment_counter(); -
优势:更精准识别"最近不常用"数据
三、淘汰过程详解
3.1 触发条件
- 写入操作时检查内存使用:
if (mem_used > server.maxmemory) - 通过
freeMemoryIfNeeded()执行淘汰
3.2 淘汰流程
graph TD
A[检查内存] -->|超过阈值| B{选择策略}
B -->|淘汰范围| C[带TTL/全量]
B -->|淘汰算法| D[LRU/LFU/随机]
C --> E[抽样检查]
D --> E
E -->|填充淘汰池| F[EvictionPoolLRU]
F -->|排序淘汰| G[释放内存]
3.3 性能优化参数
| 参数 | 默认值 | 说明 |
|---|---|---|
maxmemory-samples | 5 | 每次淘汰抽样数量 |
active-defrag-threshold-lower | 10 | 内存碎片触发主动整理的阈值 |
lfu-log-factor | 10 | LFU计数器增长速率调节因子 |
四、最佳实践指南
4.1 策略选择矩阵
| 场景特征 | 推荐策略 | 理由 |
|---|---|---|
| 热点数据频繁访问 | allkeys-lru | 保留高频访问数据 |
| 数据访问频率差异大 | volatile-lru | 避免冷数据长期占用 |
| 需要精确控制过期时间 | volatile-ttl | 优先清理即将过期数据 |
| 写入密集型应用 | noeviction | 避免淘汰引发的雪崩效应 |
4.2 配置示例
# 生产环境推荐配置
maxmemory 16gb
maxmemory-policy allkeys-lru
active-defrag yes
active-defrag-threshold-lower 10
active-defrag-threshold-upper 100
4.3 监控指标
-
关键指标:
expired_keys:每日过期Key数量evicted_keys:淘汰Key数量mem_fragmentation_ratio:内存碎片率
-
监控命令:
INFO memory MEMORY USAGE key MEMORY STATS
五、版本演进与优化
5.1 Redis 4.0+改进
- 新增LFU淘汰策略
- 优化LRU时钟精度(从秒级到毫秒级采样)
- 引入主动内存碎片整理
5.2 Redis 7.0优化
- 淘汰采样算法改进:采用更均匀的哈希桶遍历策略
- LRU/LFU参数动态调整支持
- 淘汰过程异步化(减少主线程阻塞)
六、生产问题排查
6.1 典型问题
- 内存泄漏:检查
expired_keys是否持续增长 - 淘汰抖动:观察
evicted_keys的周期性波动 - 碎片化严重:
mem_fragmentation_ratio > 1.5时触发整理
6.2 日志分析
[2025-06-05 14:30:00] : 12345 keys expired in 0.25s
[2025-06-05 14:30:01] : evicted 678 keys due to memory limit
[2025-06-05 14:30:02] : active defragmentation started (fragmentation 1.62)
通过合理配置淘汰策略并持续监控,可将缓存命中率提升至95%以上,同时将内存碎片率控制在10%以内。建议结合业务访问模式进行AB测试,选择最优策略组合。