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秒)

  • 淘汰流程

    1. 随机抽取maxmemory-samples个Key(默认5)
    2. 计算空闲时间:idle_time = (current_time - lru) * resolution
    3. 选择空闲时间最长的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-samples5每次淘汰抽样数量
active-defrag-threshold-lower10内存碎片触发主动整理的阈值
lfu-log-factor10LFU计数器增长速率调节因子

四、最佳实践指南

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测试,选择最优策略组合。