Redis穿透、雪崩、击穿
redis 经典八股文,以及生产中的应对方式。
一、缓存穿透。
redis缓存和数据库中都没有相关数据的情况下,由于redis中没有相关的数据,无法拦截,请求直接穿透到数据库,导致数据库压力过大而宕机。高并发下缓存失效的问题。指查一个不存在的数据,由于缓存无法命中,但是数据库中也没有,导致每次查询不存在的数据都需要使用存储层查询,失去了意义。
解决方案
1,运维人员可以拉黑恶意IP
2,对不存在的数据也缓存到Redis里,设置 value为null,并且设置为短期失效
3,参数处理,在field域中对相关参数进行校验,不符合校验的请求都进行拦截
4,使用布隆过滤器,不存在的key,会被布隆过滤器过滤,从而降低对数据库的压力
推荐: 目前针对于缓存穿透问题,一般在使用中,会对在 Redis和数据库中都查不到的key,缓存value为EMPTY DATA INITIALIZED
这个特殊值,当再次查询这个key的时候,直接从Redis里获取这个特殊值,就不会将大量恶意请求发往数据库。
二、缓存雪崩:大面积key在同一时间失效
设置缓存key采用了相同的过期时间,导致在某一个时刻key同时失效,请求全部转发到DB,DB瞬时压力过重,导致雪崩。
解决方案:
1,设置key永不过期
2,原有的失效时间增加一个随机值,比如1-5分钟。
3,使用redis集群部署,将热点数据均匀的分布在不同的redis节点
4,在缓存失效期通过定时任务,对即将失效的大量缓存进行更新
推荐: 目前针对于缓存雪崩问题,可以通过部署高可用的Redis集群N1、N2,将热点数据切片之后均匀存放在不同的Redis节点上,如果单个节点宕机,可以从其他节点上获取相关数据,同时加入二级缓存,如果在当前线程中获取不到数据,再查询当前 Redis集群里的数据,可以避免因单个节点宕机而引发的缓存雪崩。
三、缓存击穿
redis击穿是当某个热点key,在不停的扛着高并发的请求时,这个热点key在失效的一瞬间,持续高并发的访问会击穿缓存直接落到数据库,导致数据库压力骤升而宕机。(如果这些key在大量请求同时进来的时候失效,大量请求落到DB。)
解决方案
1,设置热点数据“永不过期
2,加上互斥锁。Redis击穿是多个线程同时去查询数据库的同一条数据,那么可以在第一个查询数据的请求上使用一个互斥锁来锁住它,让其他的线程走到这一步就等待,等第一个线程查询到了数据,然后将数据放到Redis里缓存起来。后面的线程进来发现已经有缓存了,就直接从缓存取。
推荐: 目前在我们的系统里开发了一套基于注解的缓存方案。利用Spring框架的AOP切面技术,实现Redis缓存。在高并发热点key情况下使用@CacheProperty
注解,此注解使用Redis setnx
加互斥锁的方法,执行第一条线程的查询请求,让其他线程进入等待状态,待第一个线程查完数据之后更新到Redis,其他线程可以直接查Redis,从而避免大量请求发往数据库。
总结: redis在开发中的使用的频率越来越高,也会导致相关的问题。在此,对于redis使用常见的三大问题进行了总结,并给出了一系列解决办法,并给出了比较推荐的解决方案。