# 缓存问题之缓存穿透、缓存击穿、缓存雪崩及其解决方案

# 缓存穿透

缓存穿透: 大量请求的key根本不存在于缓存中,导致请求直接到了数据库上。

解决方案

  • 缓存空值/空值缓存: 一种比较简单的解决办法,在第一次查询完不存在的数据后,将该key与对应的空值也放入缓存中,只不过设定为较短的失效时间,例如几分钟, 这样则可以应对短时间的大量的该key(重复KEY)攻击,设置为较短的失效时间则是因为该值可能跟业务无关,存在意义不大,且该次的查询也未必是攻击者发起, 没有长期存储的必要,故可以早点失效。

  • BloomFilter(布隆过滤器): 特点是肯定不存在,可能存在,所以可以把所有可能的查询条件生成一个bitmap,在进行数据库查询之前会使用这个bitmap进行过滤,如果不在其中则直接过滤,从而减轻数据库层面的压力。

# 缓存击穿

缓存击穿: 大量的请求同时查询一个key时,此时这个key正好失效,就会导致大量的请求都打到数据库上面去。(缓存击穿实际上是缓存雪崩的一个特例,是热点KEY失效问题

解决方案: 上面的现象是多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个互斥锁(分布式锁)来锁住它。 其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。

# 缓存雪崩

缓存雪崩: 当某一时刻发生大规模的缓存失效的情况,例如缓存同一时刻过期缓存服务宕机等。

解决方案

  • 对于缓存服务宕机的情况,事前可以使用集群缓存,保证缓存服务的高可用。事中可以使用本地缓存(例如:Caffeine)+ Hystrix来支撑一阵。事后开启Redis持久化机制,尽快恢复缓存集群。
  • 对于缓存同一时刻过期的情况,我们可以让他们的失效时间错开,比如在一个基础的时间上加上或者减去一个范围内的随机值。
Last Updated: 3 years ago