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

Redis 缓存穿透、缓存雪崩、缓存击穿分别是什么?

以下是 Redis 缓存穿透、缓存雪崩、缓存击穿的定义及其解决方案的详细说明:


一、缓存穿透(Cache Penetration)

定义

缓存穿透是指 查询不存在的数据,导致请求直接绕过缓存层,频繁访问数据库。通常由恶意攻击或无效请求引发。

场景示例
  • 攻击者故意请求数据库中不存在的用户 ID(如负数或极大值)。
  • 缓存未命中,导致每次请求都查询数据库。
解决方案
  1. 布隆过滤器(Bloom Filter)

    • 原理:在缓存层前加布隆过滤器,记录所有可能存在的 Key。
    • 流程
      1. 查询前先检查布隆过滤器。
      2. 若 Key 不存在,直接返回空值。
      3. 若 Key 存在,再查缓存和数据库。
    • 优点:内存占用小,效率高。
    • 缺点:有一定误判率(需权衡误判率和内存开销)。
  2. 缓存空值(Cache Null)

    • 原理:对数据库查不到的 Key,缓存一个空值(如 NULL),并设置较短过期时间。
    • 配置示例
      if (data == null) {redis.setex(key, 60, "NULL"); // 空值缓存 60 秒
      }
      
    • 优点:简单易实现。
    • 缺点:可能缓存大量无效 Key,需定期清理。
  3. 接口层校验

    • 原理:对请求参数进行合法性检查(如 ID 必须为正整数)。
    • 示例:拦截非法参数(负数、非数字字符)直接返回错误。

二、缓存雪崩(Cache Avalanche)

定义

缓存雪崩是指 大量缓存在同一时间过期,导致所有请求同时涌向数据库,引发数据库压力激增甚至宕机。

场景示例
  • 某电商首页商品缓存均设置为 24 小时过期,凌晨集中失效后,大量请求查询数据库。
解决方案
  1. 随机过期时间

    • 原理:为缓存 Key 设置基础过期时间 + 随机偏移值。
    • 示例
      int expireTime = 3600 + new Random().nextInt(600); // 3600~4200 秒
      redis.setex(key, expireTime, value);
      
    • 优点:分散缓存失效时间,降低集中访问风险。
  2. 热点数据永不过期

    • 原理:对核心数据不设置过期时间,通过后台任务异步更新。
    • 流程
      1. 缓存不设 TTL。
      2. 后台定时(如每隔 30 分钟)刷新缓存。
    • 优点:彻底避免缓存集中失效。
    • 缺点:需维护数据一致性。
  3. 多级缓存架构

    • 原理:采用本地缓存(如 Caffeine) + Redis 的多级缓存。
    • 流程
      1. 优先读取本地缓存。
      2. 本地缓存未命中时查询 Redis。
      3. Redis 未命中时查询数据库。
    • 优点:分散缓存层压力,提升容错能力。
  4. 熔断降级

    • 原理:当数据库压力过大时,暂时拒绝部分请求。
    • 工具:Hystrix、Sentinel 实现熔断机制。

三、缓存击穿(Cache Breakdown)

定义

缓存击穿是指 某个热点 Key 在缓存过期后,大量并发请求直接访问数据库,导致数据库瞬时压力过大。

场景示例
  • 某秒杀活动的商品详情缓存过期,瞬时数万请求查询数据库。
解决方案
  1. 互斥锁(Mutex Lock)

    • 原理:只允许一个线程重建缓存,其他线程等待。
    • 流程
      1. 缓存未命中时,尝试获取分布式锁(如 Redis SETNX)。
      2. 获取锁的线程查询数据库并更新缓存。
      3. 其他线程等待锁释放后重试。
    • 示例代码
      String value = redis.get(key);
      if (value == null) {if (redis.setnx(lockKey, "1")) {redis.expire(lockKey, 10); // 设置锁超时时间value = db.query(...);redis.setex(key, 3600, value);redis.del(lockKey);} else {Thread.sleep(100); // 等待后重试return getData(key); }
      }
      return value;
      
    • 优点:避免大量并发请求穿透到数据库。
    • 缺点:增加系统复杂度,可能引发线程阻塞。
  2. 逻辑过期时间

    • 原理:缓存不设置物理过期时间,但在 Value 中存储逻辑过期时间。
    • 流程
      1. 缓存 Value 包含数据内容和过期时间戳(如 {"data": "...", "expire": 1672502400})。
      2. 读取时检查逻辑过期时间,若过期则异步重建缓存。
    • 优点:无需互斥锁,保证持续可用。
    • 缺点:可能短暂返回旧数据。
  3. 热点数据预加载

    • 原理:在缓存即将过期前,提前异步刷新数据。
    • 实现:结合定时任务或消息队列(如 RocketMQ)触发更新。

四、综合对比与选型建议

问题类型核心区别推荐方案
缓存穿透查询不存在的数据布隆过滤器 + 缓存空值
缓存雪崩大量 Key 同时失效随机过期时间 + 多级缓存
缓存击穿单个热点 Key 失效互斥锁 + 逻辑过期时间

五、补充优化措施

  1. 监控与告警
    • 监控缓存命中率、数据库 QPS,设置阈值告警。
  2. 限流降级
    • 使用 Sentinel 对数据库查询接口限流,保护数据库。
  3. 数据预热
    • 高峰时段前预先加载热点数据到缓存。
  4. 集群化部署
    • Redis 集群 + 数据库读写分离,提升整体抗压能力。

通过结合业务场景选择合适的策略,可有效应对缓存相关问题,保障系统高可用性。

http://www.xdnf.cn/news/9494.html

相关文章:

  • Docker学习笔记:基础知识
  • 友达光电12.1寸液晶屏G121XN01 V001工控屏
  • 浏览器指纹科普 | 分辨率指纹是什么?
  • AMBA-AHB总线的基本操作和基本传输类型
  • B3694 数列离散化
  • python实战项目71:基于Python的US News世界大学排名数据爬取
  • 科技赋能音乐,指北科技新品闪耀广州国际乐器展
  • 【QueryServer】dbeaver使用phoenix连接Hbase(轻客户端方式)
  • 从0到1:某智慧园区数字孪生项目的技术选型复盘
  • Spring MVC极简入门:从@Reuest到Postman的全链路开发
  • 物流项目第九期(MongoDB的应用之作业范围)
  • neo4j删除所有数据
  • 常规算法学习
  • Flink 状态管理深度解析:类型与后端的全面探索
  • GNU AS汇编器的.align对齐
  • 多线程和并发之线程
  • jmeter对数据库进行单独压测
  • Spring Boot 整合 JdbcTemplate,JdbcTemplate 与 MyBatis 的区别
  • Spring AI 集成多个大语言模型
  • Android --- ObjectAnimator 和 TranslateAnimation有什么区别
  • 鸿蒙如何引入crypto-js
  • Vue3对接高德地图POI搜索
  • 容器化革命:告别传统Dockerfile,拥抱现代构建最佳实践
  • UDP数据报
  • 三十一、面向对象底层逻辑-SpringMVC九大组件之RequestToViewNameTranslator接口设计哲学
  • 随机游动算法解决kSAT问题
  • Prompt:开源库license的分类名称、说明、适应范围
  • 1.1 掌握HTML常用标签
  • 华为云Flexus+DeepSeek征文|华为云Flexus云服务器X实例上部署Dify:打造高效的开源大语言模型应用开发平台
  • 各类效果名称收集