【Redis】缓存三剑客问题实践(上)

本篇对缓存三剑客问题进行介绍和解决方案说明,下篇将进行实践,有需要的同学可以跳转下篇查看实践篇:(待发布)

缓存三剑客是什么?

        缓存三剑客指的是在分布式系统下使用缓存技术最常见的三类典型问题。它们分别是:

  • 缓存穿透:请求不存在的数据。

  • 缓存击穿:热点数据突然过期。

  • 缓存雪崩:大量数据同时过期。

        三种问题都会导致缓存失效,对数据库造成巨大压力,可能会导致数据库崩溃,引发系统性崩溃。所以说,学会如何预防和解决这三种问题显得尤为重要。


缓存穿透问题

问题描述

        缓存穿透问题指的是:当用户访问的数据即不在缓存中,又不在数据库中,也就是访问系统中不存在的数据,导致请求在访问缓存的时候发现不存在缓存,持续的去访问数据库。并且在访问数据库后,因该数据不存在导致无法构建缓存。若存在大量该请求时,数据库压力过大,可能会导致数据库崩溃。

        用一句话来说:用户请求系统中不存在的数据,导致无法构建缓存,持续访问数据库,导致系统压力过大。

可能产生的原因

        一般情况下,在我们的系统中不应该存在这种可以访问不存在的数据的方法。大概率是不好的用户进行恶意请求。比如一个用户了解到了系统中的一个API的访问方法,那么用户可以通过构建出来一个不存在的数据,然后去持续压力访问该API,就会导致缓存穿透问题的发生。

解决方案

        明确一下我们需要解决的问题:我们要解决因为缓存穿透问题导致的数据库压力过大。那么换句话来说,我们只需要将这些无效数据尽可能的在访问数据库之前屏蔽掉就好了。

方案1:缓存空数据

        如果我们发现一个API请求的数据在我们的数据库和缓存中都不存在的话,我们可以通过将这个无效数据也缓存到Redis中,若恶意请求的key值都是一致的话,就会被我们拦截在缓存,防止数据库压力过大。

        该方案也存在一些问题:

  • 如果恶意请求的数据是通过一个方式构造出来的,构造出来了大量的无效数据,那我们使用该方法可能会导致Redis中存取了大量的无效数据,这其实对Redis来说也不是很友好的。所以我们需要为这些缓存也要添加一个TTL过期时间,让Redis将这些数据在一段时间之后进行过期。需要注意的是,这个位置如果我们的过期时间设置不合理的话,也可能会出现我们后文会出现到的问题:缓存雪崩问题。

方案2:布隆过滤器

        布隆过滤器是一个比较好用的数据结构,通过布隆过滤器,我们可以快速判断一个数据是否存在我们书库中。

        布隆过滤器简单来说是由两部分组成的:一个二进制向量(也可以说是个Bit Array二进制数组)和一系列的哈希函数。

        布隆过滤器通过一个较大的bit数组用于保存所有数据,数字中每个数组只占1bit,并且每个元素的表示只能是0或1用于表示是否存在。当我们添加元素的时候,布隆过滤器通过一系列的哈希函数将数据进行计算,计算后的结果映射到数组中,将对应位置映射为1。当查询元素的时候,通过哈希函数将元素映射,查看对应位置是否均为1,如果都为1的话则表示元素可能存在我们的数据中。

        需要注意的是:如果我们查询数据映射均为1的时候,我们只能说这个元素可能存在。因为存在多个元素映射到同样的一系列位置的情况(哈希冲突)。所以我们不能一定确定数据存在。但是我们至少可以确定,如果映射的位置存在一位以上的0,那么可以说明这个数据一定不存在。


缓存击穿问题

问题描述

        缓存击穿问题指的是:当我们处于一个高并发的情况下,存在一个热点数据的访问量非常大,在我们依然存在大量请求的同时这个热点数据的缓存突然失效(可能是过期了或者被删除),导致大量的并发请求同时穿透缓存,直接访问数据库,导致数据库压力过大,可能会导致系统崩溃。

        用一句话来说:热点数据过期,导致大量并发请求穿透缓存,直接访问数据库。

可能产生的原因

        假设我们商城系统对某个商品的有秒杀活动,在秒杀商品活动结束的时候缓存过期,导致大量的后续请求直接访问到数据库中。

        本质上就是热点数据在高并发期间缓存过期。

解决方案

方案1:加互斥锁

        通过在缓存失效后,添加一个互斥锁,保证只有一个请求去查询数据库,然后更新缓存,这样就可以保证后续的请求可以正确的访问缓存,不会直接访问数据库导致数据库压力过大。

方案2:提前预热热点数据

        在发布前,我们应该对系统中存在的热点数据应该有预知的。我们可以针对热点数据进行提前预热,将其存入缓存中并设置合适的过期时间。

方案3:设置热点数据永不过期

        该方案在选用的时候需要考虑实际情况,如果我们这个热点数据是一致会被访问,也就是说这个热点数据一直都是热点数据的话,我们可以考虑设置这个热点数据永不过期。如果,热点数据是有失效性的,那么这个方案并不很适用。


缓存雪崩问题

问题描述

        缓存雪崩问题指的是:当我们存在系统中大部分缓存在同一时间失效,那么在缓存重建的过程中,如果存在大量的请求,这些请求会越过缓存直接对数据库进行访问,对数据库造成巨大的压力,可能会导致系统崩溃。当然,缓存服务器若突然宕机了,也会造成缓存雪崩问题。

可能产生的原因

  • 大量Key的TTL结束时间一致:我们设置缓存过期时间的时候可能设置的并不是很合理,导致大量的缓存在同一时间过期了,导致缓存雪崩问题。

  • 缓存服务器宕机:缓存服务都没了,所有请求肯定都会直接对数据库进行访问,形成缓存雪崩问题。

解决方案

        对于可能造成缓存雪崩的两种原因,有下面不同的解决方案:

方案1:设置随机失效时间

        通过为每个需要添加随机过期时间的Key添加随机的失效时间偏移量,避免在同一时间内有大量数据过期。

        该方案可以解决大量Key同一时间过期的情况,但是有效性也比较有限,如果存在大量数据同时添加缓存的话,该方案可能有些治标不治本。

方案2:采用多级缓存架构

        通过构建多级缓存,不同层级设置不同的过期时间策略,保证同一时间内,存在可用的缓存。

方案3:部署集群

        通过部署Redis集群,防止因为单个缓存宕机导致服务不可用。


总结

        本篇对于缓存三剑客问题进行说明,在下篇文章将对各个问题以及对应的解决方案进行实践。

【Redis】缓存三剑客问题实践(下):(待发布)

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

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

相关文章

Flink 2.0 编译

文章目录 Flink 2.0 编译第一个问题 java 版本太低maven 版本太低maven 版本太高开始编译扩展多版本jdk 配置 Flink 2.0 编译 看到Flink2.0 出来了,想去玩玩,看看怎么样,当然第一件事,就是编译代码,但是没想到这么多问…

获取印度股票市场列表、查询IPO信息以及通过WebSocket实时接收数据

为了对接印度股票市场,获取市场列表、查询IPO信息、查看涨跌排行榜以及通过WebSocket实时接收数据等步骤。 1. 获取市场列表 首先,您需要获取支持的市场列表,这有助于了解哪些市场可以交易或监控。 请求方法:GETURL&#xff1a…

云原生--CNCF-1-云原生计算基金会介绍(云原生生态的发展目标和未来)

1、CNCF定义与背景 云原生计算基金会(Cloud Native Computing Foundation,CNCF)是由Linux基金会于2015年12月发起成立的非营利组织,旨在推动云原生技术的标准化、开源生态建设和行业协作。其核心目标是通过开源项目和社区协作&am…

【Rust 精进之路之第5篇-数据基石·下】复合类型:元组 (Tuple) 与数组 (Array) 的定长世界

系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 作者: 码觉客 发布日期: 2025-04-20 引言:从原子到分子——组合的力量 在上一篇【数据基石上】中,我们仔细研究了 Rust 的四种基本标量类型&#xff1…

MongoDB 集合名称映射问题

项目场景 在使用 Spring Data MongoDB 进行开发时,定义了一个名为 CompetitionSignUpLog 的实体类,并创建了对应的 Repository 接口。需要明确该实体类在 MongoDB 中实际对应的集合名称是 CompetitionSignUpLog 还是 competitionSignUpLog。 问题描述 …

物联网 (IoT) 安全简介

什么是物联网安全? 物联网安全是网络安全的一个分支领域,专注于保护、监控和修复与物联网(IoT)相关的威胁。物联网是指由配备传感器、软件或其他技术的互联设备组成的网络,这些设备能够通过互联网收集、存储和共享数据…

PCB原理图解析(炸鸡派为例)

晶振 这是外部晶振的原理图。 32.768kHz 的晶振,常用于实时时钟(RTC)电路,因为它的频率恰好是一天的分数(32768 秒),便于实现秒计数。 C25 和 C24:两个 12pF 的电容,用于…

Jupyter Notebook 中切换/使用 conda 虚拟环境的方式(解决jupyter notebook 环境默认在base下面的问题)

使用 nb_conda_kernels 添加所有环境 一键添加所有 conda 环境 conda activate my-conda-env # this is the environment for your project and code conda install ipykernel conda deactivateconda activate base # could be also some other environment conda in…

【JAVA】十三、基础知识“接口”精细讲解!(二)(新手友好版~)

哈喽大家好呀qvq,这里是乎里陈,接口这一知识点博主分为三篇博客为大家进行讲解,今天为大家讲解第二篇java中实现多个接口,接口间的继承,抽象类和接口的区别知识点,更适合新手宝宝们阅读~更多内容持续更新中…

基于MuJoCo物理引擎的机器人学习仿真框架robosuite

Robosuite 基于 MuJoCo 物理引擎,能支持多种机器人模型,提供丰富多样的任务场景,像基础的抓取、推物,精细的开门、拧瓶盖等操作。它可灵活配置多种传感器,提供本体、视觉、力 / 触觉等感知数据。因其对强化学习友好&am…

企业微信自建应用开发回调事件实现方案

目录 1. 前言 2. 正文 2.1 技术方案 2.2 策略上下文 2.2 添加客户策略实现类 2.3 修改客户信息策略实现类 2.4 默认策略实现类 2.5 接收事件的实体类(可以根据事件格式的参数做修改) 2.6 实际接收回调结果的接口 近日在开发企业微信的自建应用时…

Linux将多个块设备挂载到一个挂载点

在 Linux 系统中,直接将多个块设备挂载到同一个挂载点是不可能的。这是因为 Linux 的文件系统挂载机制设计为一个挂载点一次只能关联一个文件系统。如果尝试将多个块设备挂载到同一个挂载点,后一次挂载会覆盖前一次的挂载,导致只有最后挂载的…

Spark-SQL(四)

本节课学习了spark连接hive数据,在 spark-shell 中,可以看到连接成功 将依赖放进pom.xml中 运行代码 创建文件夹 spark-warehouse 为了使在 node01:50070 中查看到数据库,需要添加如下代码,就可以看到新创建的数据库 spark-sql_1…

野外价值观:在真实世界的语言模型互动中发现并分析价值观

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

el-select+vue-virtual-scroller解决数据量大卡顿问题

解决el-select中数据量过大时,显示及搜索卡顿问题,及正确的回显默认选中数据 粗略的封装了组件,有需要各种属性自定义的,自己添加设置下 环境 node 16.20.1 npm 8.19.4 vue2、element-ui "vue-virtual-scroller"…

Sqlite3交叉编译全过程

Sqlite3交叉编译全过程 一、概述二、下载三、解压四、配置五、编译六、安装七、验证文件类型八、移植8.1、头文件sqlite3.h8.2、动态链接库移植8.3、静态态链接库移植 九、验证使用9.1. 关键函数说明 十、触发器使用十一、sqlite表清空且恢复id值十二、全文总结 一、概述 SQLi…

软考软件设计师考试情况与大纲概述

文章目录 **一、考试科目与形式****二、考试大纲与核心知识点****科目1:计算机与软件工程知识****科目2:软件设计** **三、备考建议****四、参考资料** 这是一个系列文章的开篇 本文对2025年软考软件设计师考试的大纲及核心内容进行了整理,并…

【数学建模】孤立森林算法:异常检测的高效利器

孤立森林算法:异常检测的高效利器 文章目录 孤立森林算法:异常检测的高效利器1 引言2 孤立森林算法原理2.1 核心思想2.2 算法流程步骤一:构建孤立树(iTree)步骤二:构建孤立森林(iForest)步骤三:计算异常分数 3 代码实现…

【Android面试八股文】Android系统架构【一】

Android系统架构图 1.1 安卓系统启动 1.设备加电后执行第一段代码:Bootloader 系统引导分三种模式:fastboot,recovery,normal: fastboot模式:用于工厂模式的刷机。在关机状态下,按返回开机 键进…

jvm-获取方法签名的方法

在Java中,获取方法签名的方法可以通过以下几种方式实现,具体取决于你的需求和使用场景。以下是详细的介绍: 1. 使用反射 API Java 提供了 java.lang.reflect.Method 类来获取方法的相关信息,包括方法签名。 示例代码&#xff1a…