Redis 缓存击穿、穿透、雪崩的原因以及解决方案

前因

最近搞了个 redis 作为记录一些频发请求以及一些经常访问,但是访问页面的数据量较大的页面。刚开始的时候没有什么问题,但是当运营到一段时间后,发现了些问题,经过查阅资料,解决了问题。所以在这里记录下。

缓存雪崩

原因描述–缓存雪崩

缓存雪崩指的是大量的请求无法在 Redis 缓存系统中处理,请求全部打到数据库,导致数据库压力激增,甚至宕机。

出现该原因主要有两种:

  1. 大量热点数据同时过期,导致大量请求需要查询数据库,数据库压力激增。
  2. Redis 故障宕机,缓存系统异常。

缓存雪崩.jpg

解决方法–缓存雪崩

方法一:过期时间添加随机值,比如 1-5 分钟随机,这样的话就能保证数据不会在同一个时间大面积失效。
方法二:服务熔断就是当从缓存获取数据发现异常,则直接返回错误数据给前端,防止所有流量打到数据库导致宕机。 方法三:接口限流,当访问的不是核心数据的时候,在查询的方法上加上接口限流保护。比如设置 10000 req/s。
如果访问的是核心数据接口,缓存不存在允许从数据库中查询并设置到缓存中。
这样的话,只有部分请求会发送到数据库,减少了压力。
方法四:提前预防,构建高可用Redis 缓存集群,主从:避免单点故障

缓存击穿

原因描述–缓存击穿

缓存击穿跟缓存雪崩有些类似,雪崩是大面积缓存失效,导致数据库崩溃,而缓存击穿是一个 key 是热点,不停地大并发请求,全都集中访问此 key,而当此 key 过期瞬间,持续的大并发就击穿缓存,全都打在数据库上。

缓存击穿.jpg

解决方法–缓存击穿

方法一:把这个热点 key 设置为永久有效
方法二:使用互斥锁,这是比较常用的方法,简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去查询数据库,而是先使用缓存工具的某些带成功操作返回值的操作(比如 Redis 的 SETNX 或者 Memcache 的 ADD)去 set 一个 mutex key,当操作返回成功时,再进行查询数据库的操作并回设缓存;否则,就重试整个 get 缓存的方法。

缓存穿透

原因描述–缓存穿透

指查询一个数据库一定不存在的数据,访问的数据既不在缓存,也不在数据库中,导致请求在访问缓存时,发生缓存缺失,再去访问数据库是,发现数据库中也没有访问的数据。最终数据不会写入缓存。在大量请求访问数据,导致缓存和数据库产生巨大压力【缓存及数据缺失,无法写入缓存】

缓存穿透.jpg

解决方法–缓存穿透

方法一:在接口层增加校验,不合法的参数直接返回。不相信任务调用方,根据自己提供的 API 接口规范来,作为被调用方,要考虑可能任何的参数传值。
方法二:在缓存查不到,DB 中也没有的情况,可以将对应的 key 的 value 写为 null,或者其他特殊值写入缓存,同时将过期失效时间设置短一点,以免影响正常情况。这样是可以防止反复用同一个 ID 来暴力攻击。
方法三:正常用户是不会这样暴力功击,只有是恶意者才会这样做,可以在网关 NG 作一个配置项,为每一个 IP 设置访问阈值。
方法四:高级用户布隆过滤器(Bloom Filter), 这个也能很好地防止缓存穿透。原理就是利用高效的数据结构和算法快速判断出你这个 Key 是否在 DB 中存在,不存在你 return 就好了,存在你就去查了 DB 刷新 KV 再 return。

一张图总结一下

GiJ4LQi2v6.png

参考文档:
1、Redis 缓存击穿、穿透、雪崩的原因以及解决方案
2、Redis 缓存击穿(失效)、缓存穿透、缓存雪崩怎么解决?

冯奎博客
请先登录后发表评论
  • latest comments
  • 总共0条评论