1. 缓存击穿(穿透)

1.1 定义

缓存穿透: 查询一个在缓存内必然不存在的数据。例如查询一篇文章的ID,这个ID在缓存和DB里面都是必然不存在的。如果类似这样的查询请求特别多,就会给DB带来很大的压力。

1.2 解决

  1. 使用BITMAP来过滤:最常见的则是采用布隆过滤器(bloom filter),将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。在JAVA里面使用布隆过滤器,可以使用guava里面的bloomFilter。如果需要基本的bitmap数据结构,可以使用util下面的BitSet。 如果关心bitmap如何自己实现可以参考SF上的回答:java - how to create and manipulate a bit array with length of 10 million bits

PS: 布隆过滤器的原理就是利用多个HASH算法将一个对象映射成一个bit数组(也称为bitmap)里面的多个点。以后判断就只要HASH后和数组里面的值亦或下就好了,效率很高。

2. 缓存雪崩

2.1 定义

缓存雪崩:可能是因为数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。

2.2 解决方法

  1. 缓存设计上用更小的粒度提升命中率
  2. 过期策略上采用较好的过期策略
  3. 提升缓存容量。例如可以用一些分布式缓存中间件,可以更好的横向扩展。现在常用的就是memcachedredis了。不过根据发展现状来说,明显redis发展的更好,新上系统都建议使用redis。详情见SF问题:Memcached vs. Redis?

参考资料:

  1. 缓存雪崩,缓存穿透解决方案
  2. 缓存穿透与缓存雪崩