缓存击穿、穿透、雪崩

当请求比较多的时候,频繁地访问数据库会给数据库带来比较大的压力,所以此时我们会使用缓存作为缓解数据库压力的一种方式。

常见的缓存更新策略

  • Cache Aside(旁路缓存)策略

    • 当修改数据时,由应用程序来更新数据库,然后同时由应用程序来更新或者删除缓存
    • 低一致性需求:使用Redis的内存淘汰机制, 最多加上超时删除来兜底。
    • 高一致性需求:主动更新,并以超时删除作为兜底方案。
  • Read/Write Through(读穿/写穿)策略

    • Read/Write Through是应用程序只和缓存交互,不再和数据库交互。让缓存和数据库交互,相当于更新数据库的操作由缓存进行
      • Read Through: 查询缓存中数据不存在时,由缓存中间件负责从数据库查询数据,并将结果写入到缓存组件,最后缓存组件将数据返回给应用
      • Write Through: 当有数据更新的时候,先更新缓存中的数据,并且由缓存组件同步更新到数据库中,然后缓存组件告知应用程序更新完成
    • 常用的缓存中间件,如Redis,往往不提供这种方式。所以业务场景中不常用
  • Write Back(写回)策略

    • Write Back策略在更新数据的时候,只更新缓存,同时将缓存数据设置为脏的,然后立马返回,并不会更新数据库。之后会通过批量异步更新的方式来更新数据库
    • Write Back 策略特别适合写多的场景, 但是带来的问题是,数据不是强一致性的,而且会有数据丢失的风险
    • Write Back常用于计算机底层。比如 CPU 的缓存、操作系统中文件系统的缓存都采用了Write Back策略. 当电脑在突然断电之后,之前写入的文件会有部分丢失,就是因为 Page Cache 还没有来得及刷盘造成的.

我们的写业务代码时通常使用旁路缓存策略,有可能出现缓存击穿、穿透、雪崩问题。

缓存雪崩

所谓缓存雪崩,一般有两种情况。

  • 同一时间大量的key都过期了,导致访问这些key的大量请求访问数据库。
  • redis宕机了,导致大量请求访问数据库。

解决方案

  • 如果是大量key同一时间过期,则给key添加固定的过期时间的基础上, 再增加一个随机的过期时间。
  • 如果是Redis宕机, 那么就使用主从或者集群保证Redis高可用。
  • 最后,做好缓存雪崩的预防是一方面。另一方面,从服务保护的角度来说,要做好服务的限流,降级,熔断策略。即使万一发生了雪崩,也能让系统提供一定程度的服务,不至于整个宕机。

缓存穿透

缓存穿透: 请求的数据在数据库和缓存中都不存在, 那么请求就会直接访问数据库.

解决方案

  • 可以缓存空对象.
    • 优点是实现简单, 维护方便
    • 缺点是空对象会带来额外的内存消耗, 有可能出现短暂的数据不一致问题, 当每次请求的key都不一样时失效
  • 使用布隆过滤器。
    • 优点是不会有多余key, 内存占用少
    • 缺点是实现复杂, 且有误判的可能

缓存击穿

缓存击穿: 缓存击穿问题也叫热点Key问题,就是一个被大量请求访问的key突然失效了,大量请求打到了数据库上。

解决方案

  • 互斥锁: 如果redis中没查到数据, 缓存未命中. 则获取互斥锁(setnx), 获取失败则休眠重试, 获取成功则再次查询缓存是否存在(双重检测), 没查到则查询数据库进行缓存重建
    • 互斥锁注重一致性, 但是性能较差, 需要数据库与缓存强一致性选择互斥锁.
  • 逻辑过期: 缓存数据时不设置过去时间,需要在将要缓存的数据中加上时间属性作为逻辑过期时间. 当缓存命中则判断是否过期, 未过期直接返回数据, 过期则获取互斥锁. 获取锁失败则说明已经有人进行缓存重建了, 那么直接返回旧数据. 获取锁成功(需要双重检测)则开启新线程进行缓存重建, 原线程直接返回保证效率.
    • 逻辑过期性能好, 但是一致性差, 需要高性能选择逻辑过期.
相关推荐
it_czz2 分钟前
LangSmith vs LangFlow vs LangGraph Studio 可视化配置方案对比
后端
蓝色王者5 分钟前
springboot 2.6.13 整合flowable6.8.1
java·spring boot·后端
花哥码天下1 小时前
apifox登录后设置token到环境变量
java·后端
hashiqimiya2 小时前
springboot事务触发滚动与不滚蛋
java·spring boot·后端
TeamDev2 小时前
基于 Angular UI 的 C# 桌面应用
前端·后端·angular.js
PPPHUANG2 小时前
一次 CompletableFuture 误用,如何耗尽 IO 线程池并拖垮整个系统
java·后端·代码规范
用户8356290780513 小时前
用Python轻松管理Word页脚:批量处理与多节文档技巧
后端·python
想用offer打牌3 小时前
一站式了解Spring AI Alibaba的流式输出
java·人工智能·后端
秋说3 小时前
华为 DevKit 25.2.rc1 源码迁移分析使用教程(openEuler + ARM64)
后端
ServBay3 小时前
C# 成为 2025 年的编程语言,7个C#技巧助力开发效率
后端·c#·.net