一、缓存穿透
在讨论缓存穿透之前,我们先来看下从缓存中读取数据时的流程,如图:
缓存穿透是什么?
如果每次都去查一个“缓存和数据库中都必不存在的数据(如id=-1的数据)”,因为缓存中不存在,那么每次请求都会打到DB上,从而导致缓存失去意义,在高并发的情况下就可能导致数据库崩溃,这就是缓存穿透。
缓存穿透的解决方案
1、规范key过滤
规范key的命名,并且统一缓存查询的入口,在入口处对key的命名格式进行检测,过滤掉不规范key的访问,这样可以过滤掉大部分的恶意攻击。如约定项目中Redis缓存key的前缀都是以"公司名_项目名_REDIS_"开头,不符合这个约定的key在一开始就过滤掉。
2、缓存空值
简单粗暴,如果查询DB返回的数据为空,我们仍然把这个空值放到Redis缓存中,只是将它的过期时间设置的很短,另外为了避免不必要的内存消耗,可以定期清理空值的key。
3、加锁
根据key从缓存中获取到的value为空时,先锁上,再去查DB将数据加载到缓存,若其它线程获取锁失败,则等待一段时间后重试,从而避免了大量请求直接打到DB。单机可以使用synchronized或ReentrantLock加锁,分布式环境需要加分布式锁