缓存穿透

  缓存穿透是指查询一个一定不存在的数据,由于缓存不会命中,需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都去数据库查询,造成缓存穿透。  

  解决方案

    1 对所有可能查询的参数以hash形式存储,在控制层进行校验,若不符合查询条件则丢弃。或者采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

    2 采用一个更为简单粗暴的方法,如果一个查询返回的数据为空,把这个空结果进行缓存,然后对这个数据设置过期时间,但它的过期时间会很短,最长不超过五分钟。

缓存雪崩

  如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,则造成了缓存雪崩。 

  解决方案

    1 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

    2 可以给缓存设置过期时间时加上一个随机值时间,使得每个key的过期时间分布开来,不会集中在同一时刻失效。

    3 设置二级缓存 : A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。

    4 缓存不过期:

      a.从缓存上看,确实没有设置过期时间,这就保证了,不会出现热点key过期问题,也就是“物理”不过期。

      b.从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期

缓存击穿  

  对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。
缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。

  解决方案

    1 加互斥锁:同本文缓存雪崩-方案一

    2 永远不过期:同本文缓存雪崩-方案四