缓存击穿、穿透、雪崩

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

常见的缓存更新策略

  • 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), 获取失败则休眠重试, 获取成功则再次查询缓存是否存在(双重检测), 没查到则查询数据库进行缓存重建
    • 互斥锁注重一致性, 但是性能较差, 需要数据库与缓存强一致性选择互斥锁.
  • 逻辑过期: 缓存数据时不设置过去时间,需要在将要缓存的数据中加上时间属性作为逻辑过期时间. 当缓存命中则判断是否过期, 未过期直接返回数据, 过期则获取互斥锁. 获取锁失败则说明已经有人进行缓存重建了, 那么直接返回旧数据. 获取锁成功(需要双重检测)则开启新线程进行缓存重建, 原线程直接返回保证效率.
    • 逻辑过期性能好, 但是一致性差, 需要高性能选择逻辑过期.
相关推荐
计算机学姐1 分钟前
基于SpringBoot的新能源充电桩管理系统
java·vue.js·spring boot·后端·mysql·spring·java-ee
瑶山12 分钟前
SpringBoot + MongoDB 5分钟快速集成:从0到1实操指南
java·数据库·spring boot·后端·mongodb
Nontee2214 分钟前
Redis 分布式锁
后端
AI_大白15 分钟前
实时行情系统的第一道槛:如何应对数据源的“限流”与“断流”
后端
Honmaple16 分钟前
阿里云 Coding Plan 终极全栈开发指南:Claude Code 与 OpenCode 模型配置全攻略
后端
农夫山泉不太甜17 分钟前
Node.js 后端服务 Socket 优化深度指南:从基础到 IM 通信实战
前端·后端
农夫山泉不太甜17 分钟前
NestJS 框架 Socket 优化实战指南
前端·后端
傲文博一18 分钟前
Microsoft Remote Desktop 能连 Mac 吗?把 Mac 远程 Mac 这件事讲透
后端
JOEH6019 分钟前
为什么你的 CPU 总是突然飙高?Java 生产环境 6 大排查误区
javascript·后端
clamlss19 分钟前
💥 踩坑实录:MapStruct 映射失效?揭秘 Lombok 组合下的编译期陷阱
java·后端