Redis 使用的过期删除策略是什么?
Redis 过期删除策略
Redis 的过期删除策略用于清理设置了过期时间(TTL)的键,主要包括: 1. 惰性删除(Lazy Deletion): - 访问键时检查是否过期,若过期则删除。 2. 定期删除(Periodic Deletion): - 定时采样检查部分键,删除过期键。
综合策略
- 惰性 + 定期:Redis 结合两者,既保证内存及时释放,又避免频繁扫描的性能开销。
核心点
- 不主动全量删除,平衡效率和内存使用。
1. 策略详解
(1) 惰性删除(Lazy Deletion)
- 原理:
- 每次访问键(如
GET
、SET
)时,检查其过期时间(TTL)。 - 若已过期,删除键并返回
nil
。 - 实现:
- Redis 在
dict
(哈希表)中存储键的过期时间戳。 - 操作时调用
expireIfNeeded
检查。 - 优点:
- 按需删除,节省 CPU。
- 缺点:
- 未访问的过期键占用内存。
- 示例:
SET key value EX 10 # 设置 10 秒过期
# 10 秒后
GET key # 检查并删除,返回 nil
(2) 定期删除(Periodic Deletion)
- 原理:
- Redis 后台线程定时(默认每秒 10 次)随机采样部分键,检查并删除过期键。
- 实现:
- 函数
activeExpireCycle
:- 从数据库随机取样(如 20 个键)。
- 检查 TTL,删除过期键。
- 若过期比例高,循环执行。
- 参数:
hz
:控制采样频率,默认 10(每秒 10 次)。- 优点:
- 主动清理,减少内存浪费。
- 缺点:
- 随机采样,可能漏删。
- 高负载下不彻底。
- 示例:
- 过期键未被访问,定期任务清理。
(3) 综合机制
- 惰性删除:处理访问时的过期键。
- 定期删除:清理未访问的过期键。
- 结果:
- 内存不会无限增长,但可能短暂残留过期键。
2. 为什么不用主动删除
- 全量定时删除:
- 遍历所有键,CPU 开销大。
- 高并发下影响性能。
- Redis 选择:
- 惰性 + 定期,兼顾性能和内存。
3. 内存淘汰策略(补充)
- 与过期删除区别:
- 过期删除针对设置了 TTL 的键。
- 内存淘汰针对内存不足时的所有键。
- 策略(
maxmemory-policy
): volatile-lru
:从过期键中按 LRU 删除。allkeys-lru
:所有键按 LRU 删除。noeviction
:不淘汰,报错。- 配置:
maxmemory 100mb
maxmemory-policy volatile-lru
4. 源码与实现
- 键结构:
redisDb
中expires
字典存储键和过期时间。- 检查逻辑:
int expireIfNeeded(redisDb *db, robj *key) {
if (!keyIsExpired(db, key)) return 0;
deleteKey(db, key); // 删除过期键
return 1;
}
- 定期任务:
serverCron
调用activeExpireCycle
。
5. 延伸与面试角度
- 与 TTL:
EXPIRE key seconds
设置过期。TTL key
查看剩余时间。- 局限:
- 高并发下定期删除不及时。
- 需配合内存淘汰。
- 实际应用:
- 缓存:过期自动失效。
- 会话:定期清理。
- 面试点:
- 问“策略”时,提惰性和定期。
- 问“优化”时,提
hz
调整。
总结
Redis 使用惰性删除(访问时检查)和定期删除(定时采样)组合清理过期键,高效平衡性能和内存。面试时,可提实现原理或举缓存示例,展示理解深度。