这篇文章,我们将介绍什么是缓存穿透、缓存击穿与缓存雪崩,以及对应的解决方案。
1.缓存穿透
缓存穿透,是指查询一个不存在的数据,由于数据不存在,所以数据不会被缓存,每次查询都是从数据库中去查询。如果有人利用这个存在的漏洞去伪造大量的请求,那么很可能导致DB承受不了那么大的流量就挂掉了。
解决方案:
- 事前预防:对所有请求进行参数校验(页面或者接口中),拒绝非法请求
- 事后预防:当查询到一个空的结果时,我们仍然将这个空的结果进行缓存,但是设置一个很短的过期时间。
2.缓存击穿
缓存击穿,就是在热点key失效的瞬间,海量的请求访问数据库,导致数据库崩溃。
解决方案:
- 互斥锁:是在缓存KEY过期去更新的时候,先让程序去获取锁,只有获取到锁的线程才有资格去更新缓存KEY。其他没有获取到锁的线程则休眠片刻之后再次去获取最新的缓存数据。通过这种方式,同一时刻永远只有一个线程会去读取数据库,这样也就避免了海量数据库请求对于数据库的冲击。
- 永不过期:将缓存设置为永不过期,通过定时任务去同步缓存和数据库的数据。
3.缓存雪崩
缓存雪崩,是指我们设置缓存时采用了相同的过期时间,导致很多key在某一时刻同时失效,请求全部转发到数据库,最终导致数据库瞬时压力过大而崩溃。
解决方案:
- 在原有失效时间的基础上增加一个随机时间(例如1-5分钟),这样每个缓存过期时间的重复率就会降低,从而减少缓存雪崩的发生。
总结:缓存穿透是业务层面的漏洞导致非法请求,与请求量、缓存失效没关系。缓存击穿则只会出现在热点数据上,发生在缓存失效的瞬间,与业务没多大关系。缓存雪崩则是因为多个 KEY 同时失效,导致数据库请求太多。非热点数据也会导致缓存雪崩,只要同时失效的 KEY 足够多。