如何避免缓存穿透,缓存击穿,缓存雪崩的疑问呢?
下文讲述Java中缓存系统的注意事项,如下所示:
由于缓存是不命中时被动写的,且出于容错考虑
此时我们需去存储层中重新查询数据,当流量过大时,会导致数据库压力过大,而崩溃
使用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力 方案2:
如果查询结果为空,也将其缓存时间,设置其缓存时间(此种方式也可拦截一部分流量)
为缓存设置不同的随机过期时间,避免缓存同一时间全部失效的现象发生
当这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据
缓存在某个时间点过期的时候,同时在此刻这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮
我们将这一种现象称之为“缓存击穿”
在开发中,当我们设计一个缓存系统时,我们需考虑以下注意事项: 避免缓存穿透、缓存击穿与失效时的雪崩效应 ---------------------------------------------------------------------- 那么如何避免这些事项呢?下文将一一到来,如下所示:
缓存穿透的概念
缓存穿透:指当我们查询一个一定不存在的数据由于缓存是不命中时被动写的,且出于容错考虑
此时我们需去存储层中重新查询数据,当流量过大时,会导致数据库压力过大,而崩溃
缓存穿透的解决方案
方案1:使用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力 方案2:
如果查询结果为空,也将其缓存时间,设置其缓存时间(此种方式也可拦截一部分流量)
缓存雪崩
缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩,我们将这一种现象称之为“缓存雪崩”缓存雪崩解决方案
方案:为缓存设置不同的随机过期时间,避免缓存同一时间全部失效的现象发生
缓存击穿
对于一些设置了过期时间的key当这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据
缓存在某个时间点过期的时候,同时在此刻这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮
我们将这一种现象称之为“缓存击穿”
缓存击穿的解决方案
使用互斥锁(mutex key)
使用mutex,在缓存失效的时候(判断拿出来的值为空)永远不过期
- 在redis上,不设置过期时间,即可保证热点key的过期问题,所有数据永不过期
- 从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。