1、什么是缓存穿透
缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。缓存穿透是指缓存和数据库中都没有的数据
2、缓存穿透的解决方案
布隆过滤器:
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力;在访问缓存层和存储层之前,将存在的key用布隆过滤器提前保存起来,做第一层拦截,当收到一个对key请求时先用布隆过滤器验证是key否存在,如果存在在进入缓存层、存储层。可以使用bitmap做布隆过滤器。这种方法适用于数据命中不高、数据相对固定、实时性低的应用场景,代码维护较为复杂,但是缓存空间占用少。
缓存空对象:
缓存空对象:是指在持久层没有命中的情况下,对key进行set(key,"")
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;
3、什么是缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。在缓存失效的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,造成后端负载加大,甚至可能会让应用崩溃。
例如:一个秒杀的场景,同时几万个用户同时抢购,缓存中没有数据,几万个用户会同时去查询数据 ,可能会造成服务器宕机。
4、缓存击穿解决方案
1、设置热点数据永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点 key 过期后产生的问题。
2、分布式互斥锁
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,该线程查询数据完成后,重建缓存set(key,value,timeout)。其他线程没有获得分布式锁的权限,因此只需要等待即可。等待缓存重构完成后重新从缓存获取数据即可。
5、什么是缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效。Redis宕机。
由于缓存层承载着大量请求,有效地保护了存储层,但是如果缓存层由于某些原因不可(宕机)或者大量缓存由于超时时间相同在同 一时间段失效(大批key失效/热点数据失效),大量请求直接到达存储层,存储层压力过大导致系统雪崩。
案例:马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
6、缓存雪崩解决方案
1、可以把缓存层设计成高可用的,即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务。利用sentinel或cluster实现。
2、 采用多级缓存,本地进程作为一级缓存,redis作为二级缓存,不同级别的缓存设置的超时时间不同,即使某级缓存过期了,也有其他级别缓存兜底
3、 缓存的过期时间用随机值,尽量让不同的key的过期时间不同