当前位置: 首页 > news >正文

缓存常见问题:缓存穿透、缓存雪崩以及缓存击穿

缓存常见问题

一、缓存穿透 (Cache Penetration)

是什么

缓存穿透是指客户端持续请求一个缓存和数据库中都根本不存在的数据。这导致每次请求都会先查缓存(未命中),然后穿透到数据库查询(也未命中)。如果这类请求量很大(比如恶意攻击,或者程序逻辑缺陷导致查询不存在的ID),就会给数据库带来巨大压力,因为每次查询都是无效的。

解决方法

  1. 缓存空值 (Cache Null Values) :
    • 当数据库查询未找到数据时,仍然在缓存中存储一个特殊标记(如null或特定字符串),并为其设置一个较短的过期时间(如1-5分钟)。这样后续对同一不存在数据的请求会命中缓存中的这个“空标记”,直接返回,避免了再次查询数据库。
  2. 布隆过滤器 (Bloom Filter) фильтр:
    • 在访问缓存和数据库之前,使用布隆过滤器预先判断请求的数据是否存在。布隆过滤器可以高效地判断一个元素“一定不存在”或“可能存在”。
    • 如果布隆过滤器判断数据不存在,则直接返回,不查询缓存和数据库,能拦截大部分对不存在数据的无效请求。
    • 需要注意布隆过滤器的误判率,以及数据写入时需要同步更新布隆过滤器。
  3. 接口层增加校验:
    • 对请求参数进行合法性校验,如用户鉴权、数据格式校验、ID范围校验等,对于不合法的请求直接拦截。

二、缓存雪崩 (Cache Avalanche)

是什么

缓存雪崩是指在短时间内,缓存中的大量Key几乎在同一时刻集中过期失效,或者缓存服务本身(如Redis集群)发生故障宕机。这两种情况都会导致原本由缓存处理的大量并发请求,在缓存失效后,瞬间直接涌向数据库,可能导致数据库压力剧增甚至崩溃。

解决方法

  1. 设置随机过期时间 (Randomized Expiration Times) :
    • 在基础过期时间上增加一个随机的偏移量(例如,过期时间 = 固定时间 + random(0, 300)秒)。这样可以避免大量Key在同一精确时刻集中失效,将过期时间点打散。
  2. 多级缓存 (Multi-level Cache) :
    • 使用例如Nginx/OpenResty的本地缓存 + Redis分布式缓存 + 数据库的架构。即使Redis层发生雪崩,前置的本地缓存也能挡住一部分流量。
  3. 服务熔断与限流 (Circuit Breaking & Rate Limiting) :
    • 当检测到数据库访问压力过大或响应缓慢时,通过熔断机制(如Sentinel, Hystrix)暂时阻止对数据库的进一步请求,直接返回降级响应(如预设的默认值或提示信息),保护数据库。
      限流则控制单位时间内访问数据库的请求数量。
  4. 保证缓存服务高可用 (High Availability for Cache Service) :
    • 对于Redis等缓存服务,搭建集群(如Redis Sentinel、Redis Cluster)或使用云服务商提供的高可用缓存服务,确保缓存服务不会轻易整体宕机。
  5. 数据预热 (Data Preheating) :
    • 在系统启动或低峰期,提前将热点数据加载到缓存中,并设置合理的过期策略。

三、缓存击穿 (Cache Breakdown / Hotspot Key Problem)

是什么

缓存击穿,也常被称为热点Key问题。它指的是某一个访问非常频繁的热点数据Key,在其对应的缓存失效的瞬间,大量针对该特定Key的并发请求同时涌入。由于缓存未命中,这些并发请求会全部直接打到数据库上查询这同一个数据,对数据库单点造成巨大压力,就像把缓存“击穿”了一个洞。

解决方法

  1. 互斥锁/分布式锁 (Mutex Lock / Distributed Lock) :
    • 当缓存未命中时,只允许一个请求线程获取锁去查询数据库并将结果写入缓存。其他线程则等待(可以设置自旋、休眠后重试,或直接返回特定提示)。一旦持有锁的线程更新了缓存并释放锁,后续请求就能从缓存获取数据。
    • 在分布式环境下,需要使用分布式锁(如基于Redis的Redisson,或基于ZooKeeper)。
    • 这是最常用的解决方案,能有效防止对数据库的并发冲击。
  2. 热点数据永不过期 (或逻辑过期) (Never Expire Hot Data / Logical Expiration) :
    • 物理永不过期:对于访问量极大且数据相对稳定的热点Key,可以考虑不设置物理过期时间,数据的更新通过后台任务主动刷新或消息通知机制来更新缓存。
    • 逻辑过期:缓存数据本身不设置TTL(或设置很长)。在缓存值中额外存储一个逻辑过期时间字段。当查询缓存命中后,判断逻辑过期时间:
      • 未过期:直接返回。
      • 已过期:启动一个异步线程去更新缓存(此过程可加锁防止并发更新),当前请求可以先返回旧数据(如果业务允许),或者等待异步更新完成。
  3. 二级缓存/本地缓存:
    • 对于极热点的数据,除了分布式缓存,还可以在应用服务器内部署本地缓存(如Caffeine, Guava Cache),降低对分布式缓存的压力,进一步减少击穿到数据库的可能性。

相关文章:

  • x86_64-apple-ios-simulator 错误
  • 分析rds的空间占用
  • VSCode远程开发-本地SSH隧道保存即时修改
  • 5.28 孔老师 nlp讲座
  • AugmentFree:解除 AugmentCode 限制的终极方案 如何快速清理vscode和AugmentCode缓存—windows端
  • 互联网大厂Java求职面试:AI大模型融合下的企业知识库架构设计与性能优化
  • 多模态大语言模型arxiv论文略读(九十九)
  • ZigBee 协议:开启物联网低功耗通信新时代
  • 在 Ubuntu 上安装 NVM (Node Version Manager) 的步骤
  • 从“固定“到“流动“:移动充电如何重塑用户体验?
  • 每日算法 -【Swift 算法】盛最多水的容器
  • 深入理解 SQL 的 JOIN 查询:从基础到高级的第一步
  • Java网络编程与Socket安全权限详解
  • Perforce P4产品简介:无限扩展+全球协作+安全管控+工具集成(附下载)
  • RFID测温芯片助力新能源产业安全与能效提升
  • android无root抓包(PCAPdroid)
  • Java消息队列与安全实战:谢飞机的烧饼摊故事
  • 智能外呼系统中 NLP 意图理解的工作原理与技术实现
  • 小型语言模型:为何“小”才是“大”?
  • 压力容器大屏监控系统 – 工业可视化HTML源码
  • 谁有做开档棉裤的网站啊/百度推广平台收费标准
  • 郑州做商城网站公司/宁波seo关键词优化制作
  • 用户要承担变压器损耗吗/网站优化怎么操作
  • wordpress 商城插件/seo技术学院
  • 吉他谱网站如何建设/西安网站制作建设
  • 南宁哪个公司做网站好/seo优化软件大全