Redis过期key三种删除策略及原理解析
一、简述
Redis 中的过期 key 到底是如何被清除的?实际上并没有单一的解决方案,而是三种策略共同作用:定时删除、定期删除、惰性删除。

其中,定时删除和定期删除属于主动触发,惰性删除则更像是被动响应。
二、定时删除
这一策略非常直观:在设置 key 过期时间的瞬间,即同时创建一个定时器。一旦时间到达,删除操作立即执行,毫不延迟。
优点:
从内存占用角度来看,定时删除是最高效的方式。过期 key 几乎能够被瞬间清理,内存释放极其及时,几乎不会残留任何脏数据。
缺点:
代价全部集中在 CPU 上。如果过期 key 数量较多,删除操作对 CPU 的消耗会非常显著。试想一下,在服务器本身请求量已很高、CPU 资源紧张的环境下,还要分出部分时间去执行这些“额外”的删除任务,这必然拖慢正常请求的响应速度,降低整体吞吐量。
更深层次的问题在于,Redis 内部的时间事件机制采用无序链表实现。查找一个事件的复杂度为 O(N),这种结构在处理少量事件时尚可,但面对大量定时器时则力不从心。因此,现阶段依靠定时器来实现大量 key 的定时删除,技术上并不现实。
三、定期删除
既然定时删除效率高但消耗 CPU,惰性删除又过于被动,那么折中方案就是“定期”出手。Redis 会按一定时间间隔主动检查数据库,并清理部分过期 key。至于具体删除多少个、检查几个库,都由内部算法动态决定。
关键在于,通过控制删除操作的执行时长和频率,Redis 避免了对 CPU 的过度占用。当然,这两个参数需要设置得恰到好处,否则策略可能偏离预期:设得太密太猛,会退化为定时删除;设得太稀太少,则与惰性删除无异。
优点:
在主动删除与 CPU 消耗之间找到了平衡点,能较为有效地控制过期 key 造成的内存浪费,同时不会严重影响服务器性能。
四、惰性删除
这一策略的哲学是“懒惰”。它不会对过期 key 做任何主动清理。只有当客户端尝试读取某个 key 时,程序才会顺便检查它是否已过期;如果过期,则顺手删除并返回空;如果未过期,则正常返回 value。
优点:
可以说是对 CPU 最友好的策略。所有的过期检查仅在“非做不可”时进行——也就是当你需要获取这个 key 的时候。而且,它只处理当前被访问的 key,绝不会在那些无人问津的过期 key 上浪费任何一个 CPU 周期。
缺点:
代价全部落在内存上。一个 key 虽然过期了,但只要没被访问,它就会一直驻留在内存中。如果数据库中存在大量过期的 key,且恰好长期无人访问,它们就会像垃圾一样永久占用内存。除非用户手动执行 flushdb 清库,否则这些内存永远不会被释放。
因此,Redis 在实际运行中采用的是定期删除 + 惰性删除的组合策略。两者相互配合,才能在 CPU 时间与内存空间之间找到最优平衡点。
五、Redis 中 flushall 和 flushdb 的区别
这两个命令都能“清空数据”,但背后的差异很大:
- flushall :清空后,会触发持久化,RDB 文件也会随之更新(会被重写为初始的 76 字节大小)。因此执行完 flushall 后,数据库彻底清空。
- flushdb :清空当前数据库,但不会触发持久化,RDB 文件保持不变。这就很有意思——Redis 启动时是从 RDB 文件加载数据的。所以清库后,如果直接 kill 掉 Redis-server 进程(注意,不要用 shutdown,因为 shutdown 会触发持久化),然后重新启动,数据就能从保存的 RDB 中完整恢复,仿佛什么都没有发生过。
需要特别留意的是:
不要使用 shutdown,它会触发持久化。正确的恢复方式是先用 lsof -i:6379 找到进程号,然后直接 kill 掉。
总结
从整体来看,Redis 的过期 key 删除策略是一门权衡的艺术——定时删除追求极致的内存管理,但代价是 CPU;惰性删除把 CPU 放在第一位,但可能造成内存泄漏;而定期删除则在两者之间寻找平衡。理解这三者的关系及其各自的代价,才能在真实业务场景中更好地配置和使用 Redis。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
Redis 7.0增量AOF重写RDB前导码配置详解
先说一个几乎所有人都踩过的典型误区:很多人把 aof-use-rdb-preamble yes 当作开启“增量重写”的开关。实际上,这个配置只干了一件事——让重写后的 AOF 文件头部带上 RDB 快照。它解决的是加载速度问题,跟“增量重写”本身的概念压根不是一回事。真正的增量重写,依赖的是 Red
在Python Tornado异步框架中安全执行SQL命令的方法与最佳实践
直接在Tornado里用SQLAlchemy同步执行SQL,结果就是阻塞IOLoop,所谓“异步框架里写同步数据库代码”,等于白搭。安全执行的关键不是“怎么写SQL”,而是“怎么不卡住事件循环”。 为什么不能在RequestHandler里直接调用session execute() 因为sessio
利用SQL触发器实现在INSERT数据时自动同步到审计表
先说结论:可以用触发器把 INSERT 数据同步到审计表,但必须用 AFTER INSERT,并且审计表的字段顺序、类型、字符集得和源表严格一致。否则,轻则写入错位、数据截断,重则直接报错、丢数据。下面把这些坑一个一个掰开说。 能,但必须用 AFTER INSERT,且审计表字段顺序、类型、字符集要
如何用SQL编写按不同工作日统计员工出勤率
在实际业务中,统计不同工作日的出勤率是HR系统里的高频需求。如果直接按日期函数分组,很容易掉进语言环境、索引失效或分母口径的坑里。下面就来拆解具体的实现要点。 必须用 CASE WHEN 将日期映射为固定 weekday 标签(如 Mon )再分组,避免语言环境导致的分组断裂;需过滤 DOW IN
Spring Boot 3动态拼接SQL为何引发严重安全漏洞
SQL注入漏洞的核心成因,本质上是因为用户输入直接参与了SQL语句的字符串拼接,而未采用参数化绑定机制。在MyBatis中使用${}、QueryWrapper中调用apply()与last()、JPA的@Query注解进行拼接等操作,都会绕过PreparedStatement的安全防护。动态字段必须
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
相关攻略
2026-07-02 09:05
2026-07-02 09:04
2026-07-02 09:04
2026-07-02 09:03
2026-07-02 09:03
2026-07-02 09:03
2026-07-02 09:03
2026-07-02 09:03
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

