面试题:Redis 数据过期后的删除策略是什么?

Redis 的 数据过期删除策略 是通过 惰性删除 和 定期删除 两种机制结合实现的,目的是在 内存占用 和 CPU资源消耗 之间取得平衡。以下是详细说明:


一、过期删除策略的核心机制

1. 惰性删除(Lazy Expiration)

  • 触发时机:当客户端尝试访问某个键(如 GETSET 等操作)时,Redis 会检查该键是否已过期。
  • 实现逻辑
    • 如果键已过期,直接删除该键并返回 NIL(空值)。
    • 如果未过期,返回键的值。
  • 优点
    • CPU友好:仅在访问键时检查过期,避免不必要的 CPU 开销。
  • 缺点
    • 内存浪费:过期但未被访问的键会一直占用内存,可能导致内存泄漏。

2. 定期删除(Periodic Expiration)

  • 触发时机:由 Redis 的周期性任务 serverCron 主动触发(默认每 100ms 执行一次)。
  • 实现逻辑
    • 分批次处理:从所有数据库中随机选取部分设置了过期时间的键,检查并删除过期键。
    • 限制条件
      • 每次最多检查 20 个键(ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)。
      • 单次删除操作的时间不超过 25ms(SLOW 模式)或 1ms(FAST 模式)。
  • 优点
    • 减少内存浪费:主动清理过期键,避免惰性删除的内存堆积问题。
  • 缺点
    • CPU消耗:随机检查和删除操作会占用一定的 CPU 资源。

二、两种策略的协同工作

Redis 同时使用惰性删除和定期删除,两者互补以优化性能:

  1. 惰性删除 处理客户端直接访问的键,确保及时清理过期数据。
  2. 定期删除 负责清理未被访问的过期键,防止内存浪费。

三、关键代码与配置

1. 惰性删除的核心函数

robj *lookupKeyRead(redisDb *db, robj *key) {
    robj *val;
    expireIfNeeded(db, key); // 检查键是否过期并删除
    val = lookupKey(db, key);
    ...
    return val;
}

2. 定期删除的核心函数

void activeExpireCycle(...) {
    ...
    while (timelimit > 0 && ...) {
        // 随机选取 20 个键进行过期检查
        for (j = 0; j < ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP; j++) {
            if (dictSize(db->expires) == 0) break;
            ...
            // 删除过期键
            if (now > when) {
                ...
                dictDelete(db->expires, key);
                server.stat_expiredkeys++;
            }
        }
    }
}

3. 配置参数

  • hz:控制 serverCron 的执行频率(默认每秒 10 次)。hz 10
  • maxmemory-policy:配合内存淘汰策略使用(如 allkeys-lru)。

四、实际场景中的表现

  1. 高并发访问场景
    • 惰性删除处理高频访问的键,定期删除清理低频访问的键。
  2. 冷数据场景
    • 依赖定期删除清理长期未被访问的过期键,避免内存堆积。
  3. 混合场景
    • 两者结合,既保证内存效率,又避免 CPU 过载。

五、常见问题与优化

1. 为什么 Redis 不使用定时删除?

  • 定时删除(为每个过期键创建定时器)会导致:
    • CPU资源浪费:大量定时器频繁触发,消耗 CPU。
    • 内存压力大:定时器本身占用额外内存。
  • Redis 选择 惰性+定期删除 的折中方案。

2. 如何优化定期删除的性能?

  • 调整 hz 值:增加 serverCron 的执行频率(如 hz 100),但需权衡 CPU 开销。
  • 控制单次扫描范围:通过 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 调整每次检查的键数量。

3. 如何避免内存泄漏?

  • 设置合理的过期时间:确保过期键能被定期删除及时扫描到。
  • 结合内存淘汰策略:当内存不足时,通过 allkeys-lru 或 volatile-ttl 等策略强制清理数据。

六、总结

策略触发时机优点缺点
惰性删除客户端访问键时CPU 友好可能导致内存泄漏
定期删除周期性任务(100ms)减少内存浪费占用一定 CPU 资源

Redis 的 惰性删除 + 定期删除 组合策略,既保证了内存的高效利用,又避免了 CPU 的过度消耗,是应对缓存场景中过期键管理的经典方案。

THE END
喜欢就支持一下吧
点赞13 分享