面试必问:Redis 缓存雪崩,别再只会背定义了

37 阅读4分钟



有一天凌晨 2 点,监控突然像过年放鞭炮一样,全红。QPS 飙升、数据库 CPU 100%、连接池打满、报警电话响到我怀疑人生。同事迷迷糊糊地问我一句:

“是不是缓存雪崩了?”

那一刻,我才真正意识到:

Redis 不只是快,它也可能是一场“雪灾”。

从一个真实又残酷的故事说起

想象一个场景。你在北方某城市生活,这座城市冬天靠集中供暖。平时大家都很舒服,屋里 25 度,外面零下十几度也不慌。

某天,供暖公司为了方便管理,统一设置:凌晨 3 点检修。结果会发生什么?

  • 3:00 整座城市同时断暖
  • 千家万户瞬间降温
  • 大家同时打开电暖气
  • 小区电闸直接拉闸
  • 整个系统彻底瘫痪

你是不是已经开始瑟瑟发抖了?

Redis 缓存雪崩,本质上就是这一幕

缓存 = 供暖系统数据库 = 电网 / 发电站请求 = 家庭用电

大量缓存在同一时间失效所有请求瞬间打到数据库,数据库扛不住,就直接“崩”。

面试官口中的标准定义

面试时你可以先给一个非常干净、标准的定义

缓存雪崩:指在某一时间点,大量缓存数据同时失效,导致原本由缓存承担的请求全部落到数据库,数据库在短时间内承受巨大压力,最终可能宕机。

如果你能补一句:

“这是高并发系统中非常典型的一类级联故障。”

面试官一般会点头。

缓存雪崩是怎么“雪”起来的?

1、最常见的作死操作:统一过期时间

很多系统,刚开始写缓存代码时是这样的:

看起来很合理,对吧?但如果你是批量加载缓存呢?

然后悲剧来了

  • 00:00 批量加载缓存
  • 00:30 所有缓存同时过期
  • 00:30:01 所有请求直冲数据库

这不是雪崩,这是定时炸弹

2、缓存节点整体不可用(进阶版雪崩)

除了过期时间问题,还有一种更狠的情况:

  • Redis 宕机
  • 网络抖动
  • 主从切换失败

这时:不是“缓存失效”,而是“缓存消失”, 所有请求,毫无缓冲,直接怼数据库。

雪崩发生时,系统会长什么样?

我们用一张表来直观感受一下:

你会发现一个事实:缓存雪崩从来不是“缓存的问题”,而是“数据库被拖下水”的问题。

解决方案一:缓存过期时间加随机值(最基础)

不要让整座城市同一秒断暖,而是:

  • 这栋楼 2:55
  • 那栋楼 3:03
  • 再远一点 3:17

分批降温,电网就能扛住。

1、正确的缓存姿势

这样做的效果:

  • 缓存不会同一时间失效
  • 数据库流量被“摊平”
  • 成本低、实现简单

2、适用场景

解决方案二:加锁排队(并发不高时最常用)

这招,在面试和实际项目里都非常常见

先说核心思想:缓存失效时,只允许一个线程去查数据库,其它线程等着。

就像:

  • 一个窗口卖票
  • 排队买
  • 不能一拥而上把窗口拆了

1、伪代码逻辑

2、执行过程拆解

3、优点与缺点

解决方案三:缓存标记位(进阶但非常优雅)

这是我非常喜欢的一种方案,因为它——像一个成熟的系统工程师思路

1、先来个生活类比

你去便利店买盒饭,发现:

  • 盒饭在
  • 但贴着一个标签: “待补货”

你会怎么做?

  • 你不会冲进后厨自己做
  • 你会等店员补货

2、技术层面的思路

缓存中不仅存数据,还存“状态”, 状态包括:

  • 是否过期
  • 是否正在重建

3、数据结构设计

3、核心代码示意

异步重建缓存

4、这种方案的特点

三种方案对比表格

面试时怎么一口气说漂亮?

如果面试官问你:

“Redis 缓存雪崩怎么解决?”

你可以这样回答:

缓存雪崩主要是由于大量缓存同一时间失效导致的。

常见解决方案包括:

第一,给缓存过期时间增加随机值,避免集中失效;

第二,在并发量不高的情况下,可以通过加锁控制只有一个线程重建缓存;

第三,更成熟的做法是引入缓存标记位或逻辑过期,缓存过期后先返回旧值,再异步更新,避免请求直接打到数据库。

这一段,说完,基本稳了

最后聊一句掏心窝子的

缓存不是银弹。

  • 它能救你
  • 也能埋你

真正成熟的系统,从来不是“用了 Redis 就万事大吉”,而是:你是否为“缓存失效的那一刻”做好了准备。

END

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

我们,下篇见。