面试官:“Redis 缓存雪崩、缓存击穿、缓存穿透分别是啥?如何解决?”,我:“。。。”
本文最后更新于2 天前,其中的信息可能已经过时,如有错误请发送邮件到2156936367@qq.com

前言

我们都知道缓存可以减少数据库压力、加快查询效率、还可以解决热点读的问题,这都是缓存的好处,那缓存有什么坏处呢?

比如说,缓存没有挡住压力,让请求都打到了数据库,这不就轧钢了,这个问题就是缓存的问题了

缓存雪崩、缓存击穿、缓存穿透的本质就是:缓存没有挡住流量,导致请求直接打到后端数据库 / 服务,最终引发数据库压力暴涨、接口超时、服务雪崩。

他们三者的区别就是:缓存为什么没有挡住流量?

缓存雪崩

什么是缓存雪崩?

大量缓存 key 在同一时间失效,或者整个缓存服务集群不可用,导致原本应该由缓存承接的流量,瞬间全部打到数据库。

正常情况其实是:Redis直接命中,然后直接返回

缓存雪崩是什么情况呢:大量key同时过期或者整个Reids集群挂了,请求全部直接打到了数据库,数据库连接数暴涨,慢查询、锁等待、CPU飙升…、接口超时、服务线程池耗尽、最终导致整个系统雪崩

解决方案

  1. 过期时间加随机值,不要让大量 key 同一时间过期。
TTL = 3600s + random(0, 600s)
  1. 热点数据永不过期,后台异步刷新
  2. 逻辑过期:热点 key 不设置物理过期时间,而是在 value 里面保存逻辑过期时间,没过期的话直接返回;过期的话返回旧数据,后台异步刷新,这样有一个问题(数据短暂不一致)
  3. Redis 高可用架构:主从、哨兵、集群、自动故障转移、多地容灾
  4. 限流、降级、熔断、MQ消息队列(从整个架构的视角)

缓存击穿

什么是缓存击穿?

某一个热点 key 在失效瞬间,大量并发请求同时访问这个 key,导致这些请求全部打到数据库。

与缓存雪崩不一样的是:他是热点key失效、不是所有key同时失效,导致这个热点key直接被打穿

比如说秒杀系统:一个热销爆款商品的key突然失效,那直接GG,数据库被打爆

解决方案

  1. 互斥锁:当热点 key 失效时,只允许一个请求去查数据库并重建缓存,其他请求等待或者稍后重试。
  1. 逻辑过期
  2. 热点数据永不过期,后台异步刷新
  3. 提前预热热点key:在大促开始前,提前把热key 写入缓存

缓存穿透

什么是缓存穿透?

请求的数据在缓存中不存在,在数据库中也不存在。每次请求都会绕过缓存,直接打到数据库。

用户请求不存在的数据,redis查不到,数据库也查不到,无法写入缓存,下次请求还是查数据库。

如果有人恶意构造大量不存在数据的ID,就很可能直接打爆数据库,缓存穿透请求一般都是非法恶意的

解决方案

  1. 缓存空值 NULL:如果数据库查不到,也把空结果(NULL)缓存起来。但是空值缓存 TTL 不宜太长(一般是30s ~ 5 min),如果后面数据库真的新增了这个 userId,但 Redis 里还缓存着 null,就会导致短时间数据不一致
  2. 布隆过滤器 BloomFilter:布隆过滤器用于判断一个数据可能存在还是一定不存在。比如说请求进来后,先经过布隆过滤器进行判断,如果缓存和数据库都不存在,就直接拒绝进入缓存,如果判断存在,再查缓存和数据库
  • 优点:内存占用小,适合拦截大量非法 key
  • 缺点:有误判率,不能删除普通元素
  1. 参数校验:很多穿透请求是明显非法的,这些请求应该在入口层直接拦截
  2. 风控、限流、黑名单:如果穿透是攻击行为,需要做安全防护

对比

对比项缓存雪崩缓存击穿缓存穿透
本质大量缓存同时失效或缓存层不可用热点 key 失效查询不存在的数据
key 数量大量 key一个或少数热点 key大量不存在的 key
数据库中是否存在通常存在存在不存在
是否热点不一定不一定
主要风险大面积请求打到数据库单个热点请求打爆数据库恶意无效请求绕过缓存
常见原因TTL 集中、Redis 宕机热点 key 过期非法参数、恶意攻击
核心方案TTL 随机、高可用、限流降级互斥锁、逻辑过期、热点预热空值缓存、布隆过滤器、参数校验

总结

  1. 缓存雪崩、击穿、穿透都是缓存失效后导致请求打到数据库的问题,但触发原因不同。
  2. 缓存雪崩是大量 key 同时失效,或者 Redis 整体不可用,导致大量请求瞬间打到数据库。常见解决方案是 TTL 加随机值、热点数据预热、Redis 高可用、限流降级和熔断。
  3. 缓存击穿是某个热点 key 过期,在高并发下大量请求同时查数据库。解决方案一般是互斥锁、逻辑过期、热点 key 永不过期、后台异步刷新。
  4. 缓存穿透是请求的数据本身不存在,缓存和数据库都查不到,导致每次请求都打到数据库。常见解决方案是缓存空值、布隆过滤器、参数校验、限流和黑名单。

当真的出现Redis事故,SRE该如何解决?

  1. 首先就是止血(限流、降级、熔断)
  2. 再定位(缓存雪崩、击穿、穿透)
  3. 恢复(根据问题类型处理)
  4. 复盘做长期治理

希望你对该篇文章Redis缓存问题有更深刻的理解,感谢观看~

觉得有帮助可以投喂下博主哦~感谢!
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
Hello! I'm 臭企鹅!