缓存穿透:查询一个不存在的数据,mysql查询不到数据不会直接写入缓存,每次都会请求数据库
发生原因:
有人恶意攻击,发布很多不存在的查询数据,大量穿过redis,访问数据库
解决方法:
- (大量占用内存,可能造成数据不一致)缓存空数据,查询返回的数据为空,扔把这个空数据缓存
- (实现复杂,可能会误判(哈希碰撞))布隆过滤器:在redis前面添加布隆过滤器,需要先预热缓存,向布隆过滤器里面添加数据,当请求的数据为空,会直接返回,不为空 再访问redis
缓存击穿:给某一个key设置了过期时间,当key过期的时候,恰好这时间点对这个可以有大量的并发请求过来,会直接把数据库压垮。
发生原因:
当热点key过期并且重建的这段时间如果耗费时间较长,就会造成缓存击穿
解决方法:
- 互斥锁(强一致,性能差):阻塞其它线程的写和获取锁,当一个线程在缓存中没有得到数据的时候,就会获取互斥锁,当完成缓存重建再释放锁,再查询缓存,成功后释放锁,此时其它被阻塞的线程可以正常执行
- 逻辑过期(高可用,不能保证一致性):给热点key加个过期字段,当过期的时候进行判断,当线程1在缓存中没有读取到数据,会先获取互斥锁,再新开一个线程2进行缓存重建,线程1不需要等待缓存重建成功,可直接返回旧的数据,为的是高可用性
缓存雪崩:同一时间段大量的缓存key同时失效或者redis服务宕机,导致大量请求直接访问数据库带来巨大压力。
发生原因 1:
大量key采用了相同的过期时间
原因1的解决方案:
给不同的key的过期时间添加随机值
发生原因 2:
redis服务器宕机
原因2的解决方案:
- 利用redis集群提高服务的高可用性 (哨兵模式,集群模式)
- 给缓存业务添加降级限流策略,前端用nginx,微服务的话用网关
- 给业务添加多级缓存(Guava,Caffeine)做一级缓存,redis做为2级缓存