Redis缓存里那种随机过期机制到底咋回事,为什么会突然失效还挺迷惑的
- 问答
- 2026-01-21 19:13:32
- 3
主要基于Redis官方文档、相关技术博客的普遍解读以及常见的系统设计实践经验)
Redis缓存里的随机过期机制,其实是为了解决一个非常实际的问题:防止大量缓存数据在同一瞬间集体失效,也就是我们常说的“缓存雪崩”。
你可以想象一下这样的场景:如果你是个负责管理仓库的人,你给仓库里所有的货物都设定了一个完全相同的保质期,比如都是30天,30天后的那个时间点,你就会面临一个灾难性的局面——所有货物同时过期,需要你一个人手忙脚乱地去把所有旧货清点、下架,然后再把所有新货上架,在这个过程中,来提货的客户(也就是你的应用程序)会发现仓库里空空如也,什么都取不到,只能干等着,系统可能就卡死或者崩溃了。
Redis缓存也是同样的道理,如果程序员在设置缓存过期时间(TTL)时,不小心或者图省事,给成千上万条关键数据都设置了完全一样的过期时间,比如都设为1小时,当1小时到达的那一刻,这些缓存数据会同时失效,紧接着,所有的用户请求就无法从快速的Redis缓存中获取数据了,它们会像潮水一样直接涌向后端脆弱的数据库,数据库瞬间承受巨大的查询压力,轻则响应变慢,拖累整个应用,重则直接宕机,导致服务完全不可用,这就是“缓存雪崩”的可怕之处。
Redis自己是怎么避免这个问题的呢?答案就是它内置的“随机过期”机制,但这需要准确理解,这个随机性并不是指在设置缓存的时候随机给个过期时间(那是程序员应该做的事),而是指在主动清理已经过期的键值对时,采用的随机采样策略。
因为Redis从设计上是一个单线程处理命令的内存数据库,它如果把所有时间都用来扫描和删除海量的过期键,那它就没办法快速响应正常的读写请求了,所以它不能像传统垃圾回收那样进行全量扫描,Redis采用的是一种“惰性删除”加“定期删除”的组合策略。
“惰性删除”很简单:当客户端尝试访问一个键时,Redis才会去检查一下这个键是否已经过期了,如果过期了,就当场删除,并返回空值,这个策略能保证过期键不会永远占着内存,但有个致命缺点:如果一个过期键再也没有被访问,那它就成了“僵尸键”,永远无法被清理,会造成内存泄漏。
光靠“惰性删除”不够,必须要有“定期删除”来主动清理,这个“定期删除”的过程,就体现了“随机”的精髓,Redis会每隔一段时间(默认是每100毫秒)就随机地抽取一定数量的键(默认是20个),检查它们是否过期,如果过期的比例很高,说明内存中过期键很多,它会立即再随机抽20个,继续清理,直到过期的比例降下来为止,如果一开始抽出来的键里过期的不多,那它就认为当前内存状况良好,这次定期清理任务就结束了。
这种随机采样抽查的方式,就像是对仓库进行随机抽查盘点,虽然我不能一次盘点所有货物,但我每次随机检查几个货架,发现临期或过期的就处理掉,这样就把集中式的、高强度的清理工作,打散成了无数个细小的、低强度的任务,分摊在了无数个100毫秒里完成,它避免了在某个时间点因为要删除巨量过期键而导致Redis服务本身出现性能抖动,从而保证了服务整体的稳定性和响应速度。
这也就解释了为什么用户会觉得“突然失效”很迷惑,Redis自身的这个机制是为了防止雪崩,但它并不能解决程序员设置过期时间过于集中所引发的问题,如果程序员真的设置了同一时间点过期,那么即使Redis自身的清理是平滑的,但在那个时间点,当大量请求到来时,由于键已经逻辑过期(即使物理上还没被随机清理进程扫到),请求还是会穿透到数据库,用户感受到的“突然失效”,根源在于过期时间设置的不合理,而不是Redis的清理机制。
结论是:Redis的随机过期机制(主要指定期删除的随机采样)是一个自我保护的精妙设计,用于平滑清理过程,防止自身被清理任务拖垮,而真正要避免业务上出现的“缓存雪崩”式突然失效,责任在于开发者,他们应该在设置缓存过期时间时,采用“基础过期时间 + 小范围随机偏差”的策略,比如原本想设1小时过期,可以实际设置为 3600 + random(0, 300) 秒,让过期时间自然分散开,从而从根本上避免大量缓存同时失效的灾难性局面。

本文由召安青于2026-01-21发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/84143.html
