一、底层存储结构
redisDb 内部包含两个核心 Dict 哈希表:
dict(keyspace):存放 key-value 数据expires:存放设置了 TTL 的 key,记录 key 对应的过期时间戳
Redis 依靠
expires字典,判断 key 是否过期。
二、两大核心过期删除策略(不会到期立刻删)
1. 惰性删除(被动删除)
- 时机:访问 key 的时候才检查过期
- 逻辑:读写 key 时,调用
expireIfNeeded,判断 key 过期时间;过期则删除,返回 nil - 优点:节省 CPU,只有用到才处理
- 缺点:长期不访问的过期 key 会一直占内存,内存泄漏风险
2. 周期删除(主动抽样清理,activeExpireCycle)
两种模式,都是抽样,不是全量扫描:
表格
| 模式 | 触发位置 | 频率 | 时间上限 | 规则 |
|---|---|---|---|---|
| SLOW | serverCron定时任务 |
server.hz 默认 10,每秒 10 次,间隔 100ms | 最多 25ms(周期的 25%) | 遍历 db,每次抽 20 个 key;超时比例 > 10% 且没到时间上限,继续抽样 |
| FAST | beforeSleep,事件循环休眠前 |
每次事件循环前,间隔≥2ms | 最多 1ms | 只有过期 key 比例 > 10% 才执行;同样抽 20 个 key,比例达标继续抽样 |
事件循环顺序:
beforeSleep(FAST清理)→ 等待 IO 事件 → 处理 IO → 到时间执行serverCron(SLOW清理)
三、整体策略总结
Redis 采用惰性删除 + 周期抽样删除组合方案:
- 惰性删除兜底:只要 key 被访问,过期一定会被清理
- 周期删除解决冷门过期 key 一直占用内存的问题
- 抽样 + 时间上限设计:避免过期 key 太多,清理操作阻塞 Redis 主线程