Redis为什么不立即删除过期Key?答案惊呆我了!

内容分享2小时前发布
0 0 0

大家好,我是你们熟悉的“小米”~一个爱折腾技术、爱喝奶茶、31岁依然热爱分享的程序员大哥哥!

前几天,我的一个读者小伙伴私信我:“小米,我昨天面试被问到一个看似简单但答不明白的问题——Redis 的过期键是怎么删除的?

当时我脑袋一片空白,只记得有个什么定时删除和惰性删除,结果被面试官一顿追问,彻底懵了……”

嘿嘿~是不是感觉这个问题“看着简单、问起来玄”?别急,今天我们就从一个故事讲起,聊聊这个Redis 的“过期键删除策略”到底是怎么回事

故事从一个“夜班Redis管理员”说起

想象一下,Redis 是一座庞大的城市,每个 Key 都像一间小屋,里面住着数据。有的屋子短租(设置了过期时间),有的屋子是永久产权(永久有效)。而 Redis,就是这座城市的勤劳管理员。

管理员的任务有三个:

记录每间屋子什么时候到期定期清理那些租期到期的屋子保证城市运行顺畅,不让垃圾数据堆成山

那么问题来了——Redis 是怎么做到的?难道管理员每时每刻都在“挨个检查”吗?那他不得累死?

别急,Redis 管理员聪明得很,它设计了三种策略,合理分工、灵活搭配,让整座城市高效又不拥堵。

Redis的三大删除策略:惰性、定期、定时

1. 定时删除(定闹钟型)

假设你租了 Redis 城市里的一间小屋(key),并告诉管理员:“我这屋子 60 秒后到期,请按时清理。”管理员点点头,立刻掏出小本本,给这间屋子绑了一个闹钟——60 秒一到,“嘀嘀嘀”,管理员马上来清空房间。

这就是定时删除(timed deletion)

它的优点是过期数据能被立刻清理,节省内存;但缺点也明显:闹钟太多会压垮管理员的CPU

想象一下——如果 Redis 里有几百万个 key,每个都绑着一个闹钟,Redis 不就成了“定时炸弹”了吗?

所以,这种方法理论上完美,实际上几乎不用。Redis 官方自己都承认:“这种方式太贵,pass。”

2. 惰性删除(懒惰型)

“我不忙着删,让我休息会儿。”

惰性删除的逻辑是这样的:Redis 不主动去找过期数据,而是当客户端访问某个 key 时,才检查它是否过期。如果发现它已经到期,Redis 就顺手删除掉它,然后返回一个空值。

就像你晚上去敲门:“咦?这屋有人吗?”管理员打开门一看,房子租期早过了,就赶紧清空。

这种方法非常省事,不会浪费 CPU。但是有个致命问题——没人访问的过期 key 永远不会被删!

于是 Redis 城市里可能藏着成堆没人住的“空房子”,白白占着内存。

3. 定期删除(抽查型)

Redis 觉得光靠懒惰可不行,得“定期巡逻”。

所以它会每隔一段时间,随机抽查一些“设置了过期时间的 key”,看看哪些该清理。

默认情况下,Redis 每秒会进行 10 次这样的抽查操作。每次随机抽取一定数量的 key(比如 20 个),检查其中哪些到期了,就顺手删除掉。如果发现“抽查到的过期 key 比例太高”,Redis 还会“继续抽查”,直到比例下降为止。

这就像管理员每隔一会儿拿着手电筒,随机翻几间屋,发现过期的就扔出去。

这样既节省 CPU,又能防止太多垃圾数据堆积。

这就是 Redis 的黄金平衡策略:

惰性删除节省性能,定期删除防止内存爆炸。

那三种策略怎么协同工作的?

其实 Redis 的做法非常聪明:

首先,当你访问 key 时,用惰性删除;其次,系统后台在“间歇性定期删除”;最后,AOF 重写或 RDB 持久化时,也会跳过过期 key。

三管齐下,让 Redis 在性能和内存之间取得完美平衡。

举个例子:

当你执行 GET user:info 时,Redis 会先看看这个 key 有没有过期;如果过期了,立刻删掉并返回空值(惰性删除);而如果你一直没访问它,Redis 每隔一阵也会自动来清理一次(定期删除)。

这就保证了:

既不会浪费性能,也不会堆满垃圾。

Redis Key 的过期时间和永久有效设置方式

那我们怎么告诉 Redis “这间屋子什么时候该清理”呢?

Redis 给了好几种“设定租期”的命令:

Redis为什么不立即删除过期Key?答案惊呆我了!

举个小故事:

小米有个缓存 user:token,我希望它 10 分钟后过期:

EXPIRE user:token 600

后来我觉得它很重要,不希望自动清除,于是执行:

PERSIST user:token

这样它就成了“永久居民”啦!

面试官常追问的问题:过期数据是怎么处理的?

这一问,可是很多同学的“翻车点”。

面试官一般会追问三连:

“过期 key Redis 会立刻删掉吗?”

“过期的数据会不会在内存里堆积?”

“持久化文件(RDB/AOF)里还会有这些过期 key 吗?”

下面小米来帮你梳理清楚:

1、Redis 不会立刻删除所有过期 key

只有定时删除策略才会“立即删”,但实际并没启用。Redis 主动清理只靠惰性 + 定期,所以不会立刻全部清理。

2、过期数据确实可能短暂存在内存里

惰性删除意味着——如果没人访问,它就不会被清。不过 Redis 的“定期清理机制”会定时回收,保证不会无限增长。

3、RDB 和 AOF 对过期 key 的处理不同

RDB(快照):在生成快照时,如果 key 已经过期,就不会写入文件;如果未过期但到恢复时已过期,会直接跳过加载。AOF(日志):在执行过期删除时,会追加一条 DEL 命令到日志,确保重放时数据一致。

所以即使 Redis 崩溃重启,也不会让已经过期的数据“死灰复燃”。

延伸思考:大规模过期key怎么办?

有个非常经典的坑:

很多同学喜欢给缓存统一设定一个固定的过期时间,比如:

EXPIRE user:cache 3600

然后批量设置上千个 key。结果一个小时后——Redis CPU 飙升,卡成幻灯片。

为什么?因为大量 key 同时过期,定期清理任务瞬间爆炸。

解决方案有两种:

1、过期时间随机化:

在设定时加一点随机偏移量,比如:expire(key, 3600 + new Random().nextInt(300));让过期时间分散,减少“雪崩”风险。

2、使用惰性+定期组合清理

Redis 已经做了性能优化,但我们在业务层也要合理规划。

总结:Redis 过期键删除策略,一句话记牢!

小米来帮你整理成口诀:

“定时删除太耗命,惰性删除懒得勤,定期抽查来平衡,性能内存都搞定!”

或者你也可以这么理解:

Redis为什么不立即删除过期Key?答案惊呆我了!

三者配合,让 Redis 在性能与资源之间找到完美平衡点。

面试建议

如果你在面试中遇到这个问题,可以这么回答:

Redis 有三种过期键删除策略:定时删除、惰性删除和定期删除。

实际使用中,Redis 主要采用惰性删除和定期删除的组合方式,定时删除因性能代价高而放弃。

对于过期 key,访问时惰性清理,后台周期性抽查清理。

RDB/AOF 持久化时会跳过过期 key,避免数据异常。

同时要注意防止大量 key 同时过期导致的性能抖动。

面试官听完一定会露出满意的微笑~

最后一句话总结:

Redis 的设计哲学是“延迟、抽样、平衡”,它不追求完美清理,而是追求系统的长久稳定。

END

如果你看到这里,不妨点个“在看”留言告诉我:

你在面试中被问过的最“坑”的 Redis 问题是什么?

说不定下一篇就是你的故事。

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!

© 版权声明

相关文章

暂无评论

none
暂无评论...