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

缓存击穿 缓存穿透 缓存雪崩

缓存击穿 缓存穿透 缓存雪崩

在日常开发中,我们经常会在后端引入 Redis 缓存来减轻数据库压力、提高访问性能。本文将逐点介绍 Redis 缓存常见问题及解决策略。

缓存穿透

  • 问题描述: 缓存穿透指的是客户端请求的数据,在缓存中和数据库中都不存在,因此每次请求都会直接绕过缓存,打到数据库上。这样缓存“形同虚设”。如果有大量此类请求,数据库可能因承受不住压力而挂掉。

  • 场景示例:

    比如购物系统中,有人恶意猜测或刷取不存在的商品 ID:用户每次请求一个在缓存和数据库都找不到的 ID。这种情况下,每次访问都要查询数据库,并发现数据不存在,无法写入缓存。如 CSDN 博客所述,“每次这个用户请求过来,都要查询一次数据库”,显然缓存不起作用,就像被穿透一样。另一种情况是业务逻辑本身产生的空查询,比如用户输入了非法参数(例如 ID 开头不符合规范),也会导致频繁请求数据库但无法命中缓存。

  • 技术原理: 由于所请求的数据本来就不存在于后端存储中,所以缓存失效,所有请求都直接穿透到数据库。缓存层无法拦截这类请求,数据库压力骤增。

  • Java 后端解决方案:

    1. 参数校验:对请求参数做严格校验。比如合法用户 ID 必须以 15 开头,如果检测到以 16 开头的非法 ID,就直接拒绝请求。这可以拦截掉部分恶意伪造的请求。

    2. 布隆过滤器:将数据库已有的数据预先加载到布隆过滤器中,对输入数据做快速存在性判断。只有布隆过滤器认定可能存在的请求才继续查询缓存或数据库;认定不存在的直接拒绝。布隆过滤器内存占用小、性能高,但存在一定误判率(可能误判数据存在)。实际应用中,如数据量较大(千万级以上),可用布隆过滤器避免大量不存在的数据请求打到数据库。

    3. 缓存空值:如果查询数据库后发现数据不存在,也在缓存中写一个空值(或特殊标记)并设置短过期时间。后续相同请求直接命中这个空值,避免重复访问数据库。正如博文所示:“当某个用户 id 在缓存中查不到,在数据库中也查不到时,也需要将该用户 id 缓存起来,只不过值是空的”,这样下次相同请求就从缓存拿到空数据,不再访问数据库。实现示例代码:

      String cacheKey = "user:" + id;
      String value = jedis.get(cacheKey);
      if (value == null) {User user = database.queryUserById(id);  // 查询数据库if (user != null) {jedis.set(cacheKey, toJson(user), "PX", 30000); // 正常缓存 30s} else {jedis.set(cacheKey, "", "PX", 5000); // 缓存空值,过期短一点}return user;
      }
      // value 可能是空字符串,直接返回 null 或处理为空情况
      return value.isEmpty() ? null : fromJson(value);
      

      以上方案实现简单、开销较低,但要注意空值占用缓存空间和适当设置过期时间。

  • 注意事项:

    • 缓存空值虽然简单,但会消耗额外的内存,且短时间内会造成一定的不一致(数据库更新后缓存空值仍然存在)。一般将空值过期时间设置得较短,定期清除。
    • 布隆过滤器能有效减少数据库访问,但需要定期同步数据并承担误判的风险。布隆过滤器是空间换时间的方案,可用于海量数据环境。

缓存击穿

  • 问题描述: 缓存击穿(又称热点 Key 问题)指的是某一个热门数据的缓存失效,在高并发下大量请求同时落到数据库。例如秒杀期间,某个热门商品的缓存正好过期,大量用户同时请求该商品信息,导致所有请求绕过缓存并发打到数据库上,数据库瞬时压力骤增,可能宕机。

  • 场景示例:

    比如电商系统举办促销活动,一件热门商品的详情被频繁浏览。为了加速响应,这件商品的信息通常会被缓存。但如果缓存 TTL 到期失效且没有及时预热,活动期间数千、上万并发请求会在同一时间查询数据库 如果有大量的用户请求同一个商品,但该商品在缓存中失效了,一下子这些用户请求都直接怼到数据库,可能会造成瞬间数据库压力过大,而直接挂掉。

  • 技术原理: 单个热点 key 失效导致数据库瞬时承受洪峰式的压力。数据库的吞吐量远低于缓存,如果没有保护措施,容易被击垮。

  • Java 后端解决方案:

    1. 加分布式锁/互斥锁:在查询数据库并重建缓存时,只允许一个线程去访问数据库,其余线程等待。常用做法是在 Redis 上使用 SETNX 加锁,伪代码如下:

      java
      复制编辑
      String lockKey = "lock:product:" + productId;
      String requestId = UUID.randomUUID().toString();
      // 尝试加锁,设置超时时间
      String result = jedis.set(lockKey, requestId, "NX", "PX", 5000);
      if ("OK".equals(result)) {// 获得锁,查询数据库并重建缓存Product prod = database.queryProductById(productId);jedis.set("product:" + productId, toJson(prod), "PX", 60000);// 释放锁if (requestId.equals(jedis.get(lockKey))) {jedis.del(lockKey);}return prod;
      } else {// 没获得锁的线程可以自旋或休眠后重试Thread.sleep(50);return getProductById(productId);
      }

      这样只有拿到锁的线程会查询数据库并写缓存,其它并发线程等待缓存更新后直接读取缓存。

    2. 自动续期(Cache 预刷新):定时任务定期访问热点数据或延长其过期时间,确保缓存持续有效,避免过期。比如设置商品缓存 30 分钟过期,但每隔 20 分钟就执行一次刷新操作,重新写入缓存并续期。

      // 定时任务
      @Scheduled(cron = "0 0/20 * * * ?")
      public void refreshHotProducts() {List<Integer> hotIds = getHotProductIds();for (int id : hotIds) {Product prod = database.queryProductById(id);jedis.set("product:" + id, toJson(prod), "PX", 1800000); // 30分钟}
      }
      
    3. 热点数据永久有效:对少数极热的数据(如即将秒杀的商品)不设置过期时间,在活动前预热缓存,活动后再清除缓存即可。这种方式虽然加大了缓存维护成本,但能彻底避免该 Key 过期带来的击穿风险。

  • 注意事项:

    • 分布式加锁需要考虑锁释放的安全性(如使用 UUID 进行比对防止误删他人锁)。
    • 自动续期在某些场景下会增加写负担,要根据实际业务决定是否适用。
    • 对活动热度可预估的场景,预热缓存 是最有效的策略:活动开始前把热门数据全拉取到缓存,活动结束后再删除缓存。

缓存雪崩

  • 问题描述: 缓存雪崩是缓存击穿的“高级版”,指在某一时间窗口内大量缓存同时失效或者缓存服务故障,导致大量请求同时穿透到数据库,产生巨大冲击。它的两种典型形式是:

    • 批量失效型: 数量众多的缓存键同时到期。
    • 服务故障型: Redis 集群或主节点宕机。

    在这两种情况下,都有大量请求透过缓存层访问数据库,数据库面临成倍的负载压力。

  • 场景示例:

    1. 缓存集体过期:例如系统缓存设置统一过期时间,到了凌晨1点很多 key 同时过期,半夜也会有流量,小流量用户访问大量未命中缓存的热点数据造成数据库压力尖峰。
    2. Redis 故障:假设 Redis 节点因为硬件故障或网络问题离线,整个缓存池不可用,所有读请求都落到数据库。

    “商品表几百万条数据已预热到 Redis 并设置了过期时间,结果某天凌晨全部过期,大量用户同时访问数据库,压力剧增”。

  • 技术原理: 缓存失效行为在短时间内剧增,导致数据库瞬时接收远超常态的请求量。Redis 服务不可用则同理,读缓存失败后落到数据库的量级成倍增长。

  • Java 后端解决方案:

    1. 设置过期时间加随机数:在设置缓存过期时间时增加一点随机值,避免所有 Key 在同一时刻到期。比如原本 TTL 是 30 分钟,可以写成 实际过期 = 30 分钟 + random(0~60秒)。简单示例:

      int baseExpire = 1800; // 30 分钟
      int randomSec = new Random().nextInt(60); // 0~59秒随机
      jedis.expire(key, baseExpire + randomSec);
      

      这样即使高并发下大量请求同时缓存,过期时间也会错开,减少瞬时失效量。

    2. 保证高可用架构:避免 Redis 单点故障。例如使用 Redis 哨兵(Sentinel)或集群模式,确保某个实例挂掉时自动进行主从切换或分片容错,防止整个缓存服务不可用。举例:部署多个 Redis 主从节点、搭建哨兵集群,当某个 Master 挂掉时,Sentinel 会自动选举新的 Master,保持缓存服务可用。

    3. 服务降级(熔断):当发现 Redis 不可用或请求过多时,可临时降级到备用方案(例如返回静态兜底数据或提示系统维护),降低数据库压力。具体可以设置一个全局开关:如果单位时间内缓存请求失败超限(例如1分钟内失败超过10次),开启降级策略,用户请求直接返回默认值或提示。后台可通过定时任务监控缓存恢复情况,条件满足时关闭降级,恢复正常服务。

  • 注意事项:

    • 随机过期只能降低同时失效的概率,不能完全避免;故常配合高可用方案使用。
    • 服务降级涉及业务逻辑设计,应根据实际场景谨慎选择。某些场景下返回“默认数据”可能会引起业务误解,需要额外评估风险。
    • 监控 Redis 内存和连接数,提前发现瓶颈,避免无预警的大量缓存过期。

数据不一致

  • 问题描述: 数据库和缓存的双写一致性问题是经典缓存应用难点。在高并发场景下,缓存和数据库之间可能出现读写错序、更新丢失等问题,导致数据库和缓存中的数据不同步,引发数据不一致现象。
  • 场景示例:现在你在开发一个电商秒杀模块 对于这种商品数量实时变化的信息 则要保证数据的强一致性 因此你决定当数据库发生变化时 让缓存也更新 非常直观 但上线后发现 数据会出现不一致性 原因是大家疯狂下单 服务器的多个线程就会同时访问 而多线程之间会有时序错乱的问题 所以用户看到的数据和你数据库实际数据不同 后来你们决定用先更新数据库 在删除缓存 但这会出现删除时大量读数据打到mysql上导致MySQL崩溃了 发生了缓存击穿 解决方法也很简单 也就是加上互斥锁 但同时还有一个小问题 当删除缓存的时候 redis中数据同时过期了 此时另一个线程也来读数据 也就会将旧数据写入redis 这样我们就可以用延时双删 也就是先删redis 在更新MySQL 再删除redis一次 这样就没问题了或者通过消息队列删除 利用消息队列的重试机制保证数据强一致性

相关文章:

缓存击穿 缓存穿透 缓存雪崩

缓存击穿 缓存穿透 缓存雪崩 在日常开发中&#xff0c;我们经常会在后端引入 Redis 缓存来减轻数据库压力、提高访问性能。本文将逐点介绍 Redis 缓存常见问题及解决策略。 缓存穿透 问题描述&#xff1a; 缓存穿透指的是客户端请求的数据&#xff0c;在缓存中和数据库中都不…...

RTC实时时钟DS1338Z-33/PT7C433833WEX国产替代FRTC1338S

FRTC1338S是NYFEA徕飞公司推出的一种高性能的实时时钟芯片&#xff0c;它采用了SOP8封装技术&#xff0c;这种技术因其紧凑的尺寸和出色的性能而被广泛应用于各类电子设备中。 FRTC1338S串行实时时钟(RTC)是一种低功耗的全二进制编码十进制(BCD)时钟/日历外加56字节的非易失性…...

Redis命令使用

Redis是以键值对进行数据存储的&#xff0c;添加数据和查找数据最常用的2个指令就是set和get。 set&#xff1a;set指令用来添加数据。把key和value存储进去。get&#xff1a;get指令用来查找相应的键所对应的值。根据key来取value。 首先&#xff0c;我们先进入到redis客户端…...

【免费数据】1980-2022年中国2384个站点的水质数据

水&#xff0c;是生命之源&#xff0c;关乎着地球上每一个生物的生存与发展。健康的水生生态系统维持着整个水生态的平衡与活力&#xff1b;更是确保人类能持续获得清洁水源的重要保障。水质数据在水质研究、海洋生物量测算以及生物多样性评估等诸多关键领域都扮演着举足轻重的…...

Java基础 Day28 完结篇

一、方法引用 对 Lambda 表达式的进一步简化 方法引用使用一对冒号 :: Tips&#xff1a;静态方法用类名加双冒号&#xff0c;非静态方法用对象名加双冒号 通过方法的名字来指向一个方法 参数可推导即可省略 可以使语言的构造更紧凑简洁&#xff0c;减少冗余代码 二、单元…...

小红薯商品搜索详情分析与实现

前言 小红书作为国内知名的社交电商平台,拥有丰富的商品数据和用户评价信息。对于数据分析师、产品经理或电商从业者来说,能够获取小红书的商品数据具有重要的商业价值。本文将详细介绍如何通过逆向工程实现小红书商品搜索API的调用。 免责声明:本文仅用于技术学习和研究目…...

Git 极简使用指南

Git 是一个强大的分布式版本控制系统&#xff0c;但入门只需要掌握几个核心概念和命令。本指南旨在帮助你快速上手&#xff0c;处理日常开发中最常见的 80% 的场景。 核心概念 仓库 (Repository / Repo): 你的项目文件夹&#xff0c;包含了项目的所有文件和完整的历史记录。…...

力扣刷题Day 69:搜索二维矩阵(74)

1.题目描述 2.思路 首先判断target是否有可能在矩阵的某一行里&#xff0c;没可能直接返回False&#xff0c;有可能就在这一行里二分查找。 3.代码&#xff08;Python3&#xff09; class Solution:def searchMatrix(self, matrix: List[List[int]], target: int) -> boo…...

c#压缩与解压缩-SharpCompress

SharpCompress SharpCompress 是一个开源项目库&#xff0c;能够处理文件。c#库对于压缩已经有很多&#xff0c;可以随意选择&#xff0c;看了SharpCompress感觉比较简洁&#xff0c;还是介绍给大家。 项目地址&#xff1a; sharpcompress 项目使用 引入nuget包&#xff1…...

Neo4j 安全深度解析:原理、技术与最佳实践

在当今数据驱动的世界中&#xff0c;图数据库承载着关键的关系信息&#xff0c;其安全性至关重要。Neo4j 提供了一套多层次、纵深防御的安全体系。 Neo4j 的安全体系提供了从认证授权到数据加密、审计追溯的完整解决方案。安全不是单一功能而是一种持续状态&#xff0c;其有效…...

MySQL指令个人笔记

MySQL学习&#xff0c;SQL语言笔记 一、MySQL 1.1 启动、停止 启动 net start mysql83停止 net stop mysql831.2 连接、断开 连接 mysql -h localhost -P 3306 -u root -p断开 exit或者ctrlc 二、DDL 2.1 库管理 2.1.1 直接创建库 使用默认字符集和排序方式&#xf…...

2022年 国内税务年鉴PDF电子版Excel

2022年 国内税务年鉴PDF电子版Excelhttps://download.csdn.net/download/2401_84585615/89784658 https://download.csdn.net/download/2401_84585615/89784658 2022年国内税务年鉴是对中国税收政策、税制改革和税务管理实践的全面总结。这份年鉴详细记录了中国税收系统的整体状…...

基于Java的OPCDA采集中间件

1.软件功能及技术特点简介&#xff1a; 软件功能及技术特点简介&#xff1a; OPCDA是基于Java语言开发的OPC client&#xff08;OPC客户端&#xff09;跨平台中间件软件&#xff0c;他支持OPC SERVER的OPC DA1.0/2.0/3.0。OPCDA实时采集数据&#xff08;包括实时数据、报警数…...

基于PyQt5的相机手动标定工具:原理、实现与应用

基于PyQt5的相机手动标定工具:原理、实现与应用 一、背景介绍二、功能详解与实现原理2.1 图像加载与预处理2.2 交互式透视调整2.3 透视变换数学原理2.4 图像拼接核心技术2.5 用户界面优化细节三、完整使用流程四、应用场景实例五、技术优势分析六、代码七、总结一、背景介绍 …...

vue2 项目中 npm run dev 运行98% after emitting CopyPlugin 卡死

今天在运行项目时&#xff0c;发现如下问题&#xff1a; 开始以为是node_modules依赖的问题&#xff0c;于是重新 npm install&#xff0c;重启项目后还是未解决。 在网上找了一圈发现有人说是 require引入图片地址没有写。在我的项目中排查没有这个问题&#xff0c;最后发现某…...

JavaScript 性能优化实战:从原理到框架的全栈优化指南

在 Web 应用复杂度指数级增长的今天&#xff0c;JavaScript 性能优化已成为衡量前端工程质量的核心指标。本文将结合现代浏览器引擎特性与一线大厂实践经验&#xff0c;构建从基础原理到框架定制的完整优化体系&#xff0c;助你打造高性能 Web 应用。 一、性能优化基础&#x…...

2025年- H61-Lc169--74.搜索二维矩阵(二分查找)--Java版

1.题目描述 2.思路 方法一&#xff1a; 定义其实坐标&#xff0c;右上角的元素&#xff08;0&#xff0c;n-1&#xff09;。进入while循环&#xff08;注意边界条件&#xff0c;行数小于m&#xff0c;列数要&#xff1e;0&#xff09;从右上角开始开始向左遍历&#xff08;比当…...

微服务商城-用户微服务

数据表 用户表 CREATE DATABASE user; USE user;CREATE TABLE user (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 用户ID,username varchar(50) NOT NULL DEFAULT COMMENT 用户名,password varchar(50) NOT NULL DEFAULT COMMENT 用户密码&#xff0c;MD5加密…...

数学复习笔记 26

5.25&#xff1a;这题还是有点难度的。主要是出现了新的知识点&#xff0c;我现在还没有那么熟悉这个新的知识点。这块就是&#xff0c;假设一个矩阵可以写成一个列向量乘以一个行向量的形式&#xff0c;这两个向量都是非零向量&#xff0c;那么这个矩阵的秩等于一。这个的原理…...

创建型-设计模式

文章目录 单例模式工厂模式建造者模式原型模式 单例模式 单例模式有饿汉式 和 懒汉式。这个我觉得无需多言&#xff0c;每个学过Java的都知道。 1.单例的使用&#xff1a;我一般就是用饿汉式&#xff0c;因为App开发的开发一般数据处理并不复杂&#xff0c;所以直接使用饿汉式…...

移动AI神器GPT Mobile:多模型自由切换

GPT Mobile是什么 GPT Mobile是一款开源的本地移动部署AI工具,主要用于安卓设备。以下是其相关介绍: 功能特点 多模型交互:支持与多个大型语言模型(LLM)同时进行对话,用户导入相应的API密钥,就可连接OpenAI、Anthropic、Google、Ollama等平台,还能根据需求自由切换不同…...

【黄金评论】美元走强压制金价:基于NLP政策因子与ARIMA-GARCH的联动效应解析

一、基本面&#xff1a;多因子模型解析黄金承压逻辑 1. 政策冲击因子驱动美元强势 通过NLP模型对关税政策文本进行情感分析&#xff0c;构建政策不确定性指数&#xff08;PUI&#xff09;达89.3&#xff0c;触发美元避险需求溢价。DSGE模型模拟显示&#xff0c;钢铁关税上调至…...

ubutu修改网关

修改Netplan配置以指定静态网关 1. 编辑Netplan配置文件 打开Netplan配置文件&#xff08;通常位于 /etc/netplan/01-netcfg.yaml 或类似路径&#xff09;&#xff1a; sudo nano /etc/netplan/01-netcfg.yaml 2. 修改配置文件 在DHCP配置基础上&#xff0c;添加静态网关和…...

Flink进阶之路:解锁大数据处理新境界

目录 一、Flink 基础回顾 二、Flink 进阶知识深入 2.1 数据类型与序列化 2.2 双流 Join 操作 2.3 复杂事件处理&#xff08;CEP&#xff09; 2.4 状态管理与优化 三、Flink 在实际场景中的应用 3.1 实时智能推荐 3.2 实时欺诈检测 3.3 实时数仓与 ETL 四、Flink 性能…...

【论文阅读】Dolphin: Document Image Parsing via Heterogeneous Anchor Prompting

Paper&#xff1a;https://arxiv.org/abs/2505.14059 Source code: https://github.com/bytedance/Dolphin 作者机构&#xff1a;字节跳动 背景 业务场景 企业数据大多数都以文本、图片、扫描件、电子表格、在线文档、邮件等文档的形式存在&#xff0c;例如&#xff1a;PDF文…...

谷歌地图免费下载手机版

软件标签: 谷歌地图 谷歌卫星高清地图 下载链接&#xff1a;夸克网盘分享 手机地图 谷歌地图免费下载(google maps)是谷歌公司打造的手机高清电子地图。2024谷歌地图官方中文版能够直观的表达出世界各地的地点&#xff0c;在地图中能够清晰的了解到自身的定位&#xff0c;让…...

DeepSeek 赋能金融衍生品:定价与风险管理的智能革命

目录 一、引言1.1 金融衍生品市场发展现状1.2 DeepSeek 的技术特点和优势1.3 研究目的和意义 二、金融衍生品定价与风险管理基础2.1 金融衍生品定价常用方法2.2 金融风险管理主要策略 三、DeepSeek 在金融衍生品定价中的应用3.1 DeepSeek 助力定价模型构建3.2 案例分析&#xf…...

SpringBoot-15-多表查询之多对多查询可选中间表

文章目录 1 mysql数据库1.1 role角色表1.2 user用户表1.3 user_role中间表2 实体类2.1 Role.java2.2 User.java3 mapper3.1 RoleMapper.java3.2 UserMapper.java4 xml4.1 RoleMapper.xml4.2 UserMapper.xml5 UserController.java6 测试7 参考附录多对多查询,一个用户可以有多个…...

论文中pdf图片文件太大怎么办

文章目录 1.使用pdf文件的打印功能将文件导出2.操作3.前后文件大小对比 1.使用pdf文件的打印功能将文件导出 该方法在保证清晰度的同时&#xff0c;内存空间也能实现减少&#xff08;如果使用线上的压缩pdf工具&#xff0c;清晰度会直线下降&#xff09; 2.操作 点击文件—&…...

简单爬虫框架实现

1. 框架功能概述 (1) HttpSession 类&#xff1a;请求管理 功能&#xff1a;封装 requests 库&#xff0c;实现带重试机制的 HTTP 请求&#xff08;GET/POST&#xff09;。关键特性&#xff1a; 自动处理 429&#xff08;请求过多&#xff09;、5xx&#xff08;服务器错误&am…...