缓存穿透:
? ? ? ?访问一个缓存和数据库都不存在的key,此时会直接打到数据库上,并且查询不到数据,没办法根据查询结果写入缓存,所以下一次请求过来还是直接访问到数据库,并且缓存也起不到作用了,每次请求都会走到数据库,流量大的话数据库可能就会挂掉。
解决方案:
1、接口校验:用户鉴权信息、数据合法性校验
2、缓存空值:访问数据库没有查询到数据时,可以将空值写入缓存,根据业务场景设置过期时间
3、设置布隆过滤器:使用布隆过滤器存储所有可能访问的key,不存在的key直接被过滤掉
缓存击穿:
? ? ? 某一个热点key,在缓存过期的一瞬间,同时有大量的请求进来,由于缓存过期了,所以这些请求都会走到数据库,造成瞬时数据库的请求量增大,导致数据库挂掉
解决方案:
1、加互斥锁:在并发的情况下,只有第一个请求能拿到锁进行数据库查询操作,其他线程拿不到锁就一直阻塞着,等第一个请求拿到数据后写入缓存,后续直接查缓存。
互斥锁的选择:
大多数都是选择Redis分布式锁,这个可以保证只有一个请求会走到数据库。
单体服务的话,可以选择JVM的锁来实现,性能要高于分布式锁;
使用锁的时候,添加锁时,要按照请求key的维度来加锁,如果使用“固定的key”加锁,会导致不同的key之间也会互相阻塞。
缓存雪崩:
? ? ? 大量热点key设置了相同的过期时间,导致缓存在同一时间全部失效,造成了数据库的请求量过大,引起雪崩,导致数据库服务挂掉,类似于升级版的缓存击穿。
解决方案:
1、过期时间打散:可以给热点key的缓存过期时间添加一个随机值时间,让这些key的缓存失效时间分布开,不会在同一时间内全部过期
2、添加互斥锁:对于同一个key,只允许一个线程去查询写入缓存,后续请求直接走缓存。