2021-06-25
缓存穿透
1. 概念
当用户查需要查询某个数据时,请求先到达Redis缓存,若Redis中没有该请求所需的数据,此时请求就会到达持久层的数据库MySQL。
若大量用户请求在Redis中都没有查到,全都请求MySQL,就会对数据库造成压力,一般这种情况多数是不正常请求,可能是黑客的恶意攻击
2. 解决方案
缓存空对象:即用户 请求在Redis中查不到数据,就会请求mysql,若mysql中也没有该请求所需数据,即为空值,并将该请求和空值存储起来,在Redis中设置一个过期时间,再次遇到相同的请求时,请求直接到达Redis,从而保护了底层的数据库
3. 方案存在的劣势
①会增加Redis存储空值的key,因此需要更多的存储空间(Redis存储数据的方式:key:value)
②即使Redis设置了空值的过期时间,但还是会造成缓存层和存储层有一段时间是数据不一致的,对某些数据一致性要求高的业务会有影响
缓存击穿
1. 概念
指Redis上某个热点key一直被大量请求访问,这个key过期失效后,就会有大量的请求涌向后端数据库,导致数据库服务崩溃
2. 解决方案
①设置热点key永不过期
②加互斥锁
即在查询持久层数据库时,保证只有一个线程能对数据库进行查询,让其他的线程睡眠几百毫秒,等待第一个线程查询完并把结果缓存到Redis中,后面的线程正常到Redis中查询,这样就不会到导致大量请求冲向持久层数据库了
3. 方案存在的劣势
设置永不过期的key是不合理的,若有很多热点key,都不设置过期时间,随着时间推移,会占用越来越多的存储空间
缓存雪崩
1. 概念
当缓存服务器或大量缓存key集中在同一时段失效,会使大量请求冲向持久层数据库服务器,导致数据库挂掉。
2. 解决方案
①Redis高可用
即搭建Redis集群,若有一台Redis宕机,还有及其他Redis服务器可继续支持工作
②限流降级
在缓存失效后,通过加锁或这队列来控制读和写数据库的线程数,比如某个可以只允许一个线程查询数据和写缓存,其他线程等待
③数据预热
即在高并发访问前,先把可能被访问的数据预先访问一遍,这样大部分数据就会加载到缓存中,在即将发生大量访问前(如618 零点秒杀),手动触发加载缓存不同的key,设置不同的过期时间,尽量让缓存失效时间均匀分布