缓存穿透、缓存雪崩、缓存击穿
系统的并发量越来越高,数据库面对大量的请求压力越来越大,所以引入了缓存技术,将高频率查询的热点数据写入缓存中,将缓存放在数据库前面,请求进来后,先从缓存中查询数据,若拿到数据则直接返回结果,若拿不到数据则请求数据库从数据库中取,数据库取到数据后更新缓存,并且返回结果,若数据库没取到,则直接返回空结果。
未添加缓存:
添加缓存后:
添加了缓存后,可能会出现缓存穿透、缓存雪崩、缓存击穿等问题
缓存穿透
客户端请求的数据,缓存和数据库中都没有。这样的请求缓存永远不会生效,所有的请求都会被打到数据库中,并且很有可能是恶意攻击。
常见的解决方案:
- 缓存空对象
- 优点:简单、维护方便
- 缺点:有额外的内存消耗、可能造成短时间的数据不一致问题!
- 布隆过滤器
- 优点:内存占用小
- 缺点:实现复杂、可能存在误判问题
其它的优化手段:
- 增加 id 的复杂度,避免被猜测 id 规律
- 做好数据的基础格式校验
- 加强用户权限校验
- 做好热点参数的限流
缓存雪崩
在同一时间段大量的缓存同时实现或者Redis宕机,导致大量的请求在同一时间段发送到了数据库。
常见的解决方案:
- 给不同的 Key 的 TTL 添加随机值
- 利用 Redis 集群的高可用性
- 给缓存业务添加降级限流策略
- 给缓存添加多级缓存
缓存击穿
缓存击穿问题也称为热点key问题,一个高并发访问并且重建业务较复杂耗时较久的 Key 突然失效,导致大量的请求瞬间到达数据库。
常见的解决方案:
- 互斥锁:在缓存未命中时,先尝试获取锁,获取锁成功后再进行查询数据库重建缓存。若此时有其它线程来获取锁,则会获取锁失败并且等待一段时间再重试。
- 逻辑过期:存储数据时,添加一个字段存储过期时间,存入 Redis 时,不设置 TTL
解决方案 | 优点 | 缺点 |
---|---|---|
互斥锁 | 没有额外的内存消耗; 保证一致性; 实现简单 | 线程需要等待,性能受影响; 可能有死锁问题 |
逻辑过期 | 线程无需等待,性能较好 | 不保证一致性; 有额外的内存消耗; 实现复杂 |
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
临川羡鱼!
喜欢就支持一下吧