1.
缓存穿透
指的是
查询一个一定不存在的数据(比如去查10000号商品,实际上只到7000号),由于缓存是不命中,将会去查询数据库,但是数据库也无此记录,我们并没有将这次查询的null写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,失去了缓存的意义。(可以理解为现在有人恶意用高并发100完的访问量去查这条,会导致数据库崩溃)
解决:将查到为null的结果放入缓存,并加入短暂的过期时间。
2.
缓存雪崩
缓存雪崩是指我们
设置缓存时key采用了相同的过期时间,(比如将10000个商品信息同时放入到缓存中)导致缓存在某一时刻同时失效,请求全部转发到数据库,数据库瞬时压力过重雪崩。
解决:原有的失效时间基础上加上一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会下降,很难引发集体失效时间。
3.
缓存击穿
对于一些设置了过期时间的key,如果这些key可能在某些时间点被超高并发访问(比如新发布的iphone手机),是一种非常
热点
的数据;
如果
这个key在大量请求同时进来前刚好失效(理解为单点key被高频访问),那么对这个key的所有查询都落到数据库上,我们称之为缓存击穿。
解决:
加锁
大并发只让一个人去查,其他人等待,查到之后释放锁,将数据存入缓存,其他人获取到锁,先去查缓存,就会有数据,不用去查数据库了。
加锁解决缓存击穿的问题
只要是同一把锁,就能锁住需要这个锁的所有线程
synchronized(this),SpringBoot的所有组件在容器中都是单例的
那么,分布式下如何加锁呢?
因为:本地锁(synchronized,JUC(lock))只能锁住当前进程,所以我们需要分布式锁
分析本地锁的时序图