Redis缓存穿透、击穿与雪崩:问题分析与解决方案

news/2025/4/1 9:50:48/文章来源:https://www.cnblogs.com/wys777/p/18800211

在现代高并发系统中,Redis作为缓存层被广泛使用,其高效的读写性能为系统提供了强大的支持。然而,在使用Redis缓存的过程中,缓存穿透、击穿和雪崩等问题可能会对系统造成严重影响。本文将围绕这些问题展开讨论,并结合Redis的特性提出具体的解决方案。

一、Redis缓存穿透:如何应对无效数据查询?

缓存穿透是指当用户请求的数据既不在Redis缓存中,也不在数据库中时,请求会直接打到数据库层,仿佛“穿透”了缓存层。这种情况通常发生在恶意攻击或误操作导致查询不存在的数据时,若不加以处理,可能导致数据库压力骤增甚至崩溃。

(一)快速拦截法:为不存在的数据设置临时缓存

为了减少对数据库的无效访问,可以在Redis中为查询不存在的数据创建一个临时键值对,并为其设置较短的过期时间。这种方法简单高效,能有效拦截后续对相同数据的重复查询,避免数据库被频繁访问。

  • 具体实现步骤

    1. 当查询Redis缓存未命中后,继续查询数据库。
    2. 若数据库中也不存在该数据,则在Redis中插入一个临时键值对,并设置一个较短的过期时间(如5分钟)。
    3. 后续对该数据的查询会命中Redis中的临时键,直接返回空值,无需再次查询数据库。
  • 优势与适用场景

    • 优势:实现简单,能够快速拦截无效请求,尤其适合防止单点恶意攻击。
    • 适用场景:适用于对性能要求较高且需要快速防护的场景。

(二)布隆过滤器:精准过滤无效请求

布隆过滤器是一种基于概率的数据结构,能够高效判断某个数据是否可能存在。结合Redis的特性,我们可以轻松实现布隆过滤器来解决缓存穿透问题。

1. 布隆过滤器的工作原理

  • 核心结构:布隆过滤器由一个大型位数组和多个无偏Hash函数组成。
  • 存储过程
    • 将每个key通过多个Hash函数计算出下标,并将对应位置的值设为1。
  • 查询过程
    • 通过相同的Hash函数计算下标,若位数组中存在0,则说明数据一定不存在;否则可能存在于Redis缓存中。

布隆过滤器工作原理

2. 实现流程

  • 前置准备:将Redis缓存中的所有key存储到布隆过滤器中。
  • 查询流程
    1. 在查询Redis缓存之前,先通过布隆过滤器判断当前key是否存在。
      • 如果布隆过滤器返回“一定不存在”,则直接返回结果,无需查询Redis或数据库。
      • 如果布隆过滤器返回“可能存在”,则继续查询Redis;若Redis未命中,再查询数据库。
  • 实际应用:Redisson提供了开箱即用的布隆过滤器实现方案,开发者可以轻松集成到现有项目中。

3. 优势与注意事项

  • 优势
    • 布隆过滤器占用内存极小,适合大规模数据的快速过滤。
    • 能够显著降低无效查询对数据库的压力。
  • 注意事项
    • 布隆过滤器存在一定的误判率(即“可能存在”但实际不存在的情况),因此需要根据业务需求调整位数组大小和Hash函数数量,以降低误判率。

通过以上两种方法,我们可以有效应对Redis缓存穿透问题,保护数据库免受无效查询的冲击。

二、Redis缓存击穿:如何应对热点数据失效?

缓存击穿是指某个热点数据的key在Redis中突然过期,导致大量请求在同一时间直接打到数据库层。这种情况通常发生在高并发场景下,若不加以处理,可能会瞬间压垮数据库。

(一)问题分析

  • 热点数据:某些数据由于访问频率极高,成为系统的“热点”,例如商品详情页、热门文章等。
  • 风险点:当这些热点数据的key在Redis中过期时,若此时有大量并发请求涌入,所有请求都会绕过缓存直达数据库,造成数据库压力骤增。

(二)解决方案

1. 热点数据永不过期

为了避免热点数据的key过期,可以采用“逻辑过期”策略,即在Redis中为热点数据设置一个永不过期的key,并通过后台定时任务定期更新缓存。

  • 具体实现步骤
    • 设置永不过期的key:在Redis中存储热点数据时,不设置过期时间。
    • 定时更新缓存
      • 使用定时任务(如每天凌晨2点)主动更新热点数据。
      • 更新流程
        1. 删除Redis中对应的key。
        2. 从数据库中查询最新数据。
        3. 将最新数据写入Redis。
    • 优势与适用场景
      • 优势:确保热点数据始终存在于Redis中,避免因key过期导致的击穿问题。
      • 适用场景:适用于访问频率极高且更新频率较低的数据。

2. 接口限流或降级策略

在高并发场景下,可以通过接口限流或降级的方式控制请求流量,避免数据库被瞬间压垮。

  • 限流策略
    • 使用工具如Redis的INCR命令或中间件(如Sentinel)限制单位时间内的请求数量。
    • 对超出限流阈值的请求直接返回友好提示或默认值。
  • 降级策略
    • 当检测到Redis缓存失效时,直接返回默认数据或静态页面,避免查询数据库。
    • 适用场景:适用于对实时性要求不高的场景。

3. 分布式锁:确保缓存重建的唯一性

在分布式环境下,当热点数据的key过期时,可能会出现多个线程同时尝试重建缓存的情况。为避免重复加载数据库,可以使用分布式锁来确保同一时刻只有一个线程负责重建缓存。

  • 实现方案
    • 基于Redisson的分布式锁
      • Redisson是Redis官方推荐的Java客户端,提供了开箱即用的分布式锁功能。
      • 示例代码:
        RLock lock = redissonClient.getLock("hot_data_lock");
        try {// 尝试加锁,最多等待10秒,锁的租约时间为30秒if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {// 查询数据库并更新缓存String data = queryDataFromDatabase();redisTemplate.opsForValue().set("hot_data_key", data);} else {// 获取锁失败,执行降级逻辑或返回默认值System.out.println("获取锁失败,执行降级逻辑...");}
        } catch (InterruptedException e) {Thread.currentThread().interrupt(); // 恢复中断状态System.out.println("线程被中断...");
        } finally {if (lock.isHeldByCurrentThread()) {lock.unlock(); // 确保当前线程持有锁时才释放锁}
        }
        
      • 优势:简单易用,适合已有Redis项目的场景,性能满足大多数需求。
    • 基于Zookeeper的分布式锁
      • Zookeeper通过临时序号节点和监听机制实现分布式锁。
      • 优势:性能较高,但需要引入额外的Zookeeper依赖,适合对性能要求较高的场景。

三、Redis缓存雪崩:如何应对大量key同时过期?

缓存雪崩是指在某一时间点,Redis中的大量key同时过期,导致请求直接打到数据库层。这种情况通常发生在缓存设计不当或系统重启后,所有缓存key在同一时间失效,从而引发数据库压力骤增甚至崩溃。

(一)问题分析

  • 风险点
    • 当大量key在同一时间过期时,所有请求都会绕过Redis直接访问数据库。
    • 数据库无法承受如此高的并发请求,可能导致服务不可用。
  • 常见场景
    • 系统初始化时,所有缓存数据在同一时间加载并设置相同的过期时间。
    • 定时任务批量更新缓存时未考虑过期时间的分布。

(二)解决方案

1. 分布式锁:控制缓存重建的并发

当大量key同时过期时,可以通过分布式锁确保同一时刻只有一个线程负责重建缓存,避免多个线程同时加载数据库。

2. 热点数据永不过期

为了避免热点数据的key过期,可以采用“逻辑过期”策略,即不为热点数据设置过期时间,而是通过后台定时任务主动更新缓存。

3. 随机设置key的过期时间

为了防止大量key同时过期,可以在设置缓存时为每个key添加一个随机的过期时间偏移量。例如,原本设置的过期时间为1小时,可以在此基础上增加一个随机值(如0~5分钟)。

  • 实现方式
    int baseExpireTime = 60 * 60; // 基础过期时间:1小时
    int randomOffset = ThreadLocalRandom.current().nextInt(300); // 随机偏移:0~5分钟
    redisTemplate.opsForValue().set("cache_key", data, baseExpireTime + randomOffset, TimeUnit.SECONDS);
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/907939.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java - 使用OpenCV + Tesseract识别图片验证码

java - 使用OpenCV + Tesseract识别图片验证码tesseract tesseract-ocr/tesseract: 是一个开源的光学字符识别(OCR)引擎,适用于从图像中提取和识别文本。特点是可以识别多种语言,具有较高的识别准确率,并且支持命令行和API调用。项目地址:https://gitcode.com/gh_mirror…

【笔记】力扣 2316. 统计无向图中无法互相到达点对数——并查集, + 一种巧妙的求两两相乘之和的方法

2316. 统计无向图中无法互相到达点对数 中等 提示 给你一个整数 n ,表示一张 无向图 中有 n 个节点,编号为 0 到 n - 1 。同时给你一个二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示节点 ai 和 bi 之间有一条 无向 边。 请你返回 无法互相到达 的不同 点对数目 。 示例…

APT Package Manager

from pixivWhat is APT? Anatomy of the Package System(软件包系统剖析), is the Debian packaging system, 用于管理软件包,可以将其想象成命令行版的App Store.Debian 是一个自由且开源的 Linux 发行版,Ubuntu 是基于 Debian 构建的 Linux 发行版。它由 Canonical 公司…

22.1-任务的状态 第22章-FreeRTOS项目实战--任务的创建与执行 FreeRTOS 项目 FreeRTOS学习笔记 FreeRTOS移植 FreeRTOS开源项目 FreeRTOS面试题汇

这个是全网最详细的STM32项目教学视频。 第一篇在这里: 视频在这里: https://www.bilibili.com/video/BV16x4y1M7EN/?share_source=copy_web&vd_source=f5d5850ab773377dff308188468fbc77 STM32智能小车V3-STM32入门教程-openmv与STM32循迹小车-stm32f103c8t6-电赛 嵌入式…

ART树在订单簿管理中的应用

背景近期在工作中,我接触到了一种高效的数据结构——自适应基数树(Adaptive Radix Tree,ART)。ART 是一种基于基数树(Radix Tree)的数据结构,旨在提供高效的键值存储和查找功能。与传统的基数树不同,ART 通过自适应调整节点大小(如 Node4、Node16、Node48 和 Node256)…

AtCoder Beginner Contest 399 ABCDEF 题目解析

A - Hamming Distance 题意 给定两个长度均为 \(N\) 的字符串 \(S\) 和 \(T\),求总共有多少个位置不同。 思路 直接输入字符串后逐位判断即可。 代码 int n; string s, t; cin >> n >> s >> t; int ans = 0; for(int i = 0; i < n; i++)ans += (s[i] != …

Solana编译失败探讨(OpenEuler RISC-V版)

Solana 是 2017 年由 Anatoly Yakovenko 创立的开源项目,旨在打造高性能、去中心化且低成本的区块链平台2。它采用独特的 Proof of History(PoH)共识机制,结合 Tower BFT 等技术,实现了每秒数千笔交易的高吞吐量,确认时间仅 400 毫秒,每笔交易中位数费用为 0.00064 SOL1…

windows将ollama及模型安装到D盘或其他盘符

Ollama官网 在ollama安装包存放的文件路径输入 cmd 回车自动打开命令窗口 在命令行输入一下内容: 软件包名称 /DIR=指定目录OllamaSetup.exe /DIR=E:\software\Ollama 弹出安装程序,直接Install ---------------------------------------------------------------------…

【DIY】通达信DIY添加扫雷宝、地图和复盘(1)

【写在前面】炒股软件有很多,电脑版我用的多的通达信,手机版用的多的是同花顺。之前还有一些其它的软件,比如A股通、短线王、wind股票、雪球等都有自己的特色。自己不喜欢一次装好多软件,所以就产生了聚合的念头。通达信通赢版可以登录多券商账号,懒得来回切换,所以选择以…

RabbitMQ进阶--TTL,死信队列,持久化,磁盘监控

一.消息的TTL机制 RabbitMQ中的TTL(Time-To-Live,存活时间)是指消息或队列的过期时间。TTL机制允许你指定消息在未被消费前可以存活的时间长度,超过这个时间后,消息将被视为“死亡”,并从队列中移除。这种机制对于控制消息的有效性和资源管理非常有用。 防止积压消息:当…

day41 基础的模块

基础模块 ad-hoc命令模式pingcommandshellcopyfilescriptcrongroupuser1.先看资料,看模块的语法 - 官网,看实例用法,语法注解 - ansible-doc -s 模块名 - 你自己的学习笔记2.每一个模块独有的参数语法,都是 ad-hoc命令模式ansible 主机组 -m 模块名 -a "模块独有的…

Java面试基础

一、Java基础语法 1.1 环境搭建与开发 1、JDK、JRE、JVM的关系和区别?(高频plus)JDK:Java Development Kit,Java开发工具包,包含了JRE和一系列Java开发工具。 JRE:Java Runtime Environment,Java程序的运行环境,包含JVM、Java核心类库等。JRE只能用来运行Java应用程序…