一、前言
通常在我们的项目中,为了提高访问速率,会使用NoSql进行缓存,Redis属于使用广泛的一种,但使用它又可能出现,缓存穿透,缓存击穿,缓存雪崩等问题。
二、介绍
1、缓存穿透
缓存穿透问题在一定程度上与缓存命中率有关。key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,那么,数据访问的绝大部分压力都会集中在后端数据库层面。
2、缓存击穿
如果我们为缓存中的大部分数据设置了相同的过期时间,则到了某一时刻,缓存中的数据就会批量过
期,导致大部分用户的请求都会直接落在数据库上,这种现象就叫作缓存击穿。
3、缓存雪崩
当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,数据存储层的调用量就会暴增,用不了多长时间,数据库就会被大流量压垮,这种级联式的服务故障,就叫作缓存雪崩。
三、缓存穿透解决方案
(1)、由于请求的参数是不合法的(每次都请求不存在的参数),于是我们可以使用布隆过滤器(BloomFilter)或者压缩filter提前拦截,不合法就不让这个请求到数据库层。
(2)、当我们从数据库找不到的时候,我们也将这个空对象设置到缓存里边去。下次再请求的时候,就可以从缓存里边获取了。这种情况我们一般会将空对象设置一个较短的过期时间。
四、缓存击穿解决方案
缓存击穿的情况下一般不容易造成DB的宕机,只是会造成对DB的周期性压力。对缓存击穿的解决方案一般可以这样:Redis中的数据不设置过期时间,然后在缓存的对象上添加一个属性标识过期时间,每次获取到数据时,校验对象中的过期时间属性,如果数据即将过期,则异步发起一个线程主动更新缓存中的数据。但是这种方案可能会导致有些请求会拿到过期的值,就得看业务能否可以接受,如果要求数据必须是新数据,则最好的方案则为热点数据设置为永不过期,然后加一个互斥锁保证缓存的单线程写。
五、缓存雪崩解决方案
(1)、数据预热,就是系统上线后,将相关的缓存数据直接刷新到缓存中,这样就可以避免用户请求先查数据库。可以通过缓存Reload机制,预热刷新缓存。
(2)、双缓存策略,C1为原始缓存,C2为拷贝缓存,C1失效时,可以访 问C2,C1缓存失效时间设置为短期,C2设置为长期。
(3)、key值的过期时间设置为随机,防止同一时间大量的数据过期。
(4)、将Redis缓存部署成高可用集群(必要时候做成异地多活),可以有效的防止缓存雪崩问题的发生。