一、概述
正常情况下,大量的资源请求都会被redis响应,在redis得不到响应的小部分请求才会去请求DB,这样DB的压力是非常小的,是可以正常工作的。三者出现的根本原因:Redis命中率下降,请求直接打在DB上
如果大量的请求在redis上得不到响应,那么就会导致这些请求会直接去访问DB,导致DB的压力瞬间变大而卡死或者宕机。:
- 大量的高并发的请求打在redis上
- 这些请求发现redis上并没有需要请求的资源,redis命中率降低
- 因此这些大量的高并发请求转向DB(数据库服务器)请求对应的资源
- DB压力瞬间增大,直接将DB打垮,进而引发一系列“灾害”
二、分析
缓存穿透:
- 缓存穿透产生的原因:请求根本不存在的资源(DB本身就不存在,Redis更是不存在)
- 举例(情景在线):客户端发送大量的不可响应的请求
解决方式:
- 对空值进行缓存
- 从而进行(黑客)黑名单的设置限制服务
- 接口校验 无效访问就直接拦截,不允许这些请求到达Redis、DB上。
注意事项:
- 使用空值作为缓存的时候,key设置的过期时间不能太长,防止占用太多redis资源
- 对空值缓存是一种被动的防御方式,当遇到黑客暴力请求很多不存在的数据就需要写入大量的null值到Redis中,可能导致Redis内存占用不足的情况
缓存击穿:
key 对应的数据存在,但在 redis 中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端 DB 加载数据并回设到缓存,这个时候大量并发的请求可能会瞬间把后端 DB 压垮(redis某个热门数据过期,大量的合理数据请求到达数据库)
解决方式:
- 预先设置:加大这些热门数据 key 的时长
- 实时调整: 现场监控哪些数据热门,实时调整 key 的过期时长
- 使用锁:(1)就是在缓存失效的时候(判断拿出来的值为空),不是立即去 load DB;(2) 先使用缓存工具的某些带成功操作返回值的操作(比如 Redis 的 SETNX)去 set 一个 mutex key;(3) 当操作返回成功时,再进行 load db 的操作,并回设缓存,最后删除 mutex key;(4) 当操作返回失败,证明有线程在 load db,当前线程睡眠一段时间再重试整个 get 缓存的方法
缓存雪崩:
缓存雪崩产生的原因:redis中大量的key集体过期,那么这时候如果有大量并发的请求来到,那么redis就无法进行有效的响应(命中率急剧下降),请求就都打到DB上了,到时DB直接崩溃
解决方式:
- 将失效时间分散开:通过使用自动生成随机数使得key的过期时间是随机的,防止集体过期
- 使用锁或者队列的方式:如果查不到就加上排它锁,其他请求只能进行等待