缓存穿透与缓存雪崩的解决方案
1、缓存穿透
缓存穿透是指用户查询个别key时,该key不存在,导致用户请求转向数据库查询,而数据库中也不存在,那么该key对应的value就一直不会被缓存,从而导致所有针对该key的请求全部转向数据库查询,使整个缓存系统对该key失去作用,我们称这种现象为缓存穿透。
那么缓存穿透一般该如何解决呢?
通常来说,目前业内比较常见的方法有两种:
a、缓存空的对象;
缓存空的对象,这就意味着,当用户请求了不存在的key时,我们在缓存中存在一个空值对象。这么做其实有如下问题:
(1)、如果空值的对象过多,仍然可能导致缓存系统的内存空间被占用,增加缓存系统的压力。
(2)、而且当数据库中拥有了该key对应的非空value时,在过期时间到来之前,仍然同样会存在数据不一致的情况。
b、采用布隆过滤器过滤掉针对不存在的key的查询请求。
我们这里就不聊布隆过滤器的原理了,读者有兴趣,可以自己另行去研究一下。
采用这种办法,我们可以有效的将大量针对不存在的key的查询请求直接给过滤掉。
这种办法有这些好处:
(1)、不用浪费更多的缓存空间去存储空值的kv对;
(2)、有效减少针对缓存系统的查询请求。
但这种办法,也有一些缺点:
(1)、由于布隆过滤器的假阳性率问题,导致并不能过滤掉100%的针对不存在value的key的查询请求。
(2)、如果之前不存在value的key,在某一个时间,它在数据库中有了对应的value之后呢,那么我们需要保持对布隆过滤器中bitmap的数据更新,否则会出现过滤掉存在value的key的情况。
2、缓存雪崩
缓存雪崩是什么呢?它也是缓存穿透的一种极端情况,通常由于大量的key同时过期或者缓存系统的宕机等原因,导致缓存系统几乎失去作用,引发大量的请求转向数据库查询,大量请求针对数据库的查询,有可能引发数据库系统的崩溃,而数据库系统的崩溃还有可能引发一连串的依赖数据库系统的应用的崩溃,故称为雪崩。
为了解决缓存雪崩问题,通常可以采用下面三种办法:
a、保证缓存系统的高可用(如何保证,是另外的话题,我们会在其它的文章中予以讨论);
b、数据预热,在系统启动阶段,我们就提前初始化好缓存系统中的数据,保证用户的大量请求过来可以命中缓存;
c、避免所有的热点key的集中过期,也就是我们可以将这些key的过期时间,设置为不同的过期时间,通常设置为一个固定时间值+一个随机的时间段。
具体如何选取,需要根据我们业务要求来进行权衡,但是一定要尽量避免我们的系统中发生缓存雪崩的现象,因为一旦发生,它就是巨大的灾难。