1、缓存雪崩
缓存雪崩,是指在某一时间段,缓存集中过期失效。所有原本应该访问缓存的请求都去查询数据库而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃。
1.1、解决方案
(一)加锁或者队列
可以考虑用加锁或者队列的方式防止大量线程对数据库的一次性进行读写,避免缓存失效时对数据库造成的巨大冲击。
(二)协调Redis过期时间
分析用户行为,尽量让缓存失效的时间均匀分布,最次也得随机分布,尤其是一些访问大的接口。
(三) 二级缓存
做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。
2、缓存穿透
缓存穿透,是指查询一个一定不存在的数据。由于缓存不命中,并且出于容错考虑,如果从数据库查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,失去了缓存的意义。
2.1、解决方案
(一)布隆过滤器(BloomFilter)
采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。由于请求的参数是不合法的(每次都请求不存在的参数),于是我们可以使用布隆过滤器(BloomFilter)或者压缩filter提前拦截,不合法就不让这个请求到数据库层。
(二) 将空对象记录在缓存中
如果数据库返回信息为null,也可以将这个空对象设置到缓存里边去。下次再请求的时候,就可以从缓存里边获取了,将空对象设置一个较短的过期时间。
3、缓存击穿
缓存击穿,是指的是热点key在某个特殊的场景时间内恰好失效了,恰好有大量并发请求过来了,造成DB压力。
3.1、解决方案
(一)加锁或者队列
和缓存雪崩解决方案相同。
(二)过期时间可以无限调长
将热点key过期时间无限调长,然后通过job服务来管理这些热点key不会过期,保证热点key(尤其是像排行榜、首页热度等需要大量计算的热点key)的稳定性。需要注意的是,job服务本身也存在不稳定性,比如部署job的服务挂了之类的。