缓存穿透
查询一个用不存在的数据,由于缓存不命中,将去查数据库。但此时数据库也无此记录,并且我们并没有将查询为null的结果写入缓存,这导致这个不存在的数据每次请求都去数据库中查找,失去缓存的意义。
风险:
利用不存在的数据对数据库进行攻击,最终导致数据库压力增大,数据库崩溃;
解决方案:
- 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0,直接拦截;
2. 对查询不到的内容,也将其缓存到redis中,并设置短暂的过期时间;
3. 使用布隆过滤器。类似于一个hash set,用于快速判断某个元素是否存在于该集合中。其典型的应用场景就是快速判断一个key是否存在于某容器,不存在就直接返回。布隆过滤器的关键就在于hash算法和容器大小。
缓存雪崩
指我们设置缓存时key采用了相同的过期时间,导致某一时刻缓存同时失效,大面积key请求全部转发到DB,DB瞬时压力过大而导致雪崩;
解决方案:
- 在失效时间上增加一个随机值,避免集体失效;
- 如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中;
- 设置热点数据永不过期;
缓存击穿
对于一些设置了过期时间的key,如果这些key在某些时间点被超高并发访问,是一种非常“热点”的数据;
如果这个key在大量请求的同时进来前正好失效,那么所有对这个key的数据都会落到db上;
解决方案:
- 加锁: 大量并发只允许一个线程查,其他人等待,查到以后释放锁,其他线程获取到锁之后,先查缓存,查不到在去查db;
- 接口限流与熔断,降级。重要的接口一定要做好限流策略,防止用户恶意刷接口,同时要降级准备,当接口中的某些服务不可用时候,进行熔断,失败快速返回机制;