Redis篇之缓存雪崩、击穿、穿透详解
学习材料:https://xiaolincoding.com/redis/cluster/cache_problem.html
缓存雪崩
什么是缓存雪崩
在面对业务量较大的查询场景时,会把数据库中的数据缓存至redis中,避免大量的读写请求同时访问mysql客户端导致系统崩溃。这种情况下,客户端进来的请求会先经过redis缓存查询,如果redis缓存过期则进而去查询mysql,而后再将返回的结果返回给客户端并再redis中进行缓存。于是就出现了一个问题,如果此时redis中大量的缓存数据过期或者redis宕机,那么客户端发起的请求还是会直接访问到数据库中,会使得数据库的压力剧增,导致数据库奔溃进而导致系统崩溃,这就是缓存雪崩问题。
示意图如下:
如何解决缓存雪崩问题
针对不同的诱因,有不同的应对策略;
1、大量数据同时过期
- 均匀设置过期时间;应该尽量避免将大量数据设置同一个过期时间,比如可以过期时间加上一个随机数,这样就可以保证数据不会在同一个时间过期。
- 互斥锁;当业务线程处理用户请求时发现请求的数据不在redis中,则加入一个互斥锁,保证这个时间内只有一个请求来进行缓存构建。拿不到锁的请求要么就返回空值或者默认值,要么就等构建完成之后再来获取缓存。(需要设置超时时间,避免拿到锁的请求崩溃后导致系统阻塞崩溃)
- 后台更新缓存;把更新缓存的工作交由后台线程定时更新。
2、Redis宕机
- 服务熔断;服务熔断就是一旦redis发生宕机,那么所有对缓存服务的访问全部返回错误,这样的话业务线会全部无法正常工作,但是系统不会崩溃。
- 请求限流机制;限流机制就是一旦redis发生宕机,只允许少量的请求访问数据库,再多的请求则在入口直接拒绝访问,这种可以减少对业务的影响。
- 构建redis缓存高可用集群;通过主从节点的方式构建redis缓存的高可用集群。
缓存击穿
什么是缓存击穿?
一般在秒杀活动这种大量访问某几个数据的情况下会出现此问题。也就是某几个热点数据同时过期,也会导致大量的请求击垮数据库,这种情况就叫做缓存击穿。
如何解决缓存击穿?
缓存击穿其实可以认为是缓存雪崩中缓存过期的一种情况,所以可以采用互斥锁或者后台更新缓存的方式来解决。
缓存穿透
什么是缓存穿透
在缓存和数据库中都没有相关的业务数据,此时就没办法构建缓存来服务后续的请求。当有大量这样的请求进入时,业务缓存中查询不到数据且无法构建缓存,就会不停的查询数据库导致数据库压力过大甚至系统崩溃,这就叫缓存穿透。
导致缓存穿透的原因有哪些
- 业务误操作将查询的数据进行了删除。
- 黑客攻击,故意大量访问某些读取不存在数据的业务
如何解决缓存穿透
- 限制非法请求;在API入口处进行判断请求是否合理,不合理的直接拦截避免进一步访问缓存或者数据库。
- 缓存空值或默认值;如果发现线上业务出现缓存穿透的现象,可以给这些值设置一个空值或者默认值返回,避免访问数据库。
- 使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在;
缓存雪崩、击穿、穿透的产生原因及其应对方案简述如下
补充问题
在面对并发请求时如何通过加互斥锁来避免缓存雪崩或者缓存击穿的问题?
在客户端请求进来之后,如果缓存中没有查询到数据,则使用setNX的方式来设置一个状态位,表示一种锁定状态。如果返回结果是0说明锁已经被占领,此时进行等待状态。如果返回结果是1则去请求数据库,将数据库中的数据读取到了之后再将此查询的key设置缓存共其他请求进行查询。这样就可以保证在并发请求中只会有一个请求查询数据库,其他请求只能等待重新发起查询,从而解决缓存并发问题。
解决缓存热点问题
那么缓存策略的总体思路:就是通过判断数据最新访问时间来做排名,并过滤掉不常访问的数据,只留下经常访问的数据,具体细节如下。
- 先通过缓存系统做一个排序队列(比如存放 1000 个商品),系统会根据商品的访问时间,更新队列信息,越是最近访问的商品排名越靠前。
- 同时系统会定期过滤掉队列中排名最后的 200 个商品,然后再从数据库中随机读取出 200 个商品加入队列中。
- 这样当请求每次到达的时候,会先从队列中获取商品 ID,如果命中,就根据 ID 再从另一个缓存数据结构中读取实际的商品信息,并返回。
- 在 Redis 中可以用 zadd 方法和 zrange 方法来完成排序队列和获取 200 个商品的操作。
如何保证缓存一致性
- 等待过期:等待redis中的key过期之后再重新去数据库读取数据进行更新。
- 优点
- 开发成本低、易实现
- 管理成本低,出现问题的概率小
- 缺点
- 完全依赖过期时间,时间太短容易导致缓存失效频繁,太长如果导致数据不一致。
- 优点
- 尝试删除:在更新数据库数据时尝试删除redis中的key,如果删除成功下次查询该缓存时就会查询到数据库层然后再去更新缓存
- 优点
- 延迟更小,数据一致性比方案一更高
- 实现成本低
- 缺点
- 如果数据库更新成功,但是redis删除失败,就会出现方案一的问题
- 在高并发场景容易出现连接数过多的问题
- 优点
- 主动更新:另外搭建一个消费服务订阅消息队列,再数据库数据更新时异步更新redis中的数据
- 优点
- 比较可靠,能保证更新操作至少在redis中执行了一次
- 解耦度高
- 缺点
- 实现成本高,需要另外增加消费服务
- 有时序性问题,如果因为网络延迟导致同一条数据的两次更新推送没有按照更新的顺序来,也会出现数据不一致问题
- 依然有客户端连接数过多问题
- 优点
- 订阅日志:搭建一个消费服务去订阅数据库的binlog日志,解析日志内的内容再去更新redis,实现与业务完全解耦
- 优点
- 在服务器压力不大的情况下,延迟最低
- 与业务解耦
- 解决了时序性问题,可靠性强
- 缺点
- 需要单独搭建一个同步服务,成本高
- 如果同步服务崩溃,会导致数据长时间不更新
- 优点
方案选型
如果数据变化多,且对数据的一致性要求高,那么直接不用缓存;
通常来说使用方案一就够了,如果要增加更新的即时性,就用方案二,如果对于延时要求高就用方案三或四,四能解决时序性问题。具体需要结合业务场景调整。
拓展:缓存如何保证高可用?
主从复制模式、哨兵模式、Redis Cluster模式
使用主从复制搭建的Redis集群可以实现读写分离的效果,一般使用一主多从,主写从读。但是这种模式有个问题就是一旦主从机有宕机的情况,就需要人工介入进行IP切换。
哨兵模式则是在主从复制的基础上进行了升级,加入了哨兵,也就是当主机宕机时会通过哨兵的检测判定是否下线,判定下线后会在其他的从机中选出一台主机然后调整其他从机的主机IP。
而Redis Cluster模式不仅有以上两种模式的优点,且其会将数据分节点存储,充分利用内存。Redis Cluster划分了16384个槽,每个key通过CRC16校验后对16384进行取模来决定放置哪个槽,集群的每个节点负责一部分的hash槽。这样就避免了不同节点中的内存数据冗余。
相关文章:

Redis篇之缓存雪崩、击穿、穿透详解
学习材料:https://xiaolincoding.com/redis/cluster/cache_problem.html 缓存雪崩 什么是缓存雪崩 在面对业务量较大的查询场景时,会把数据库中的数据缓存至redis中,避免大量的读写请求同时访问mysql客户端导致系统崩溃。这种情况下&#x…...

【深度学习笔记】3_2线性回归的从零实现
注:本文为《动手学深度学习》开源内容,仅为个人学习记录,无抄袭搬运意图 3.2 线性回归的从零开始实现 在了解了线性回归的背景知识之后,现在我们可以动手实现它了。尽管强大的深度学习框架可以减少大量重复性工作,但若…...
Apache Maven简介
Maven 简介 Apache Maven 是一个用于项目构建、依赖管理和项目信息管理的强大工具。它基于项目对象模型(Project Object Model,POM)进行构建,通过描述项目的结构和依赖关系来管理项目的构建过程。 以下是 Apache Maven 的一些关键原理和工作流程: 项目对象模型(POM)…...
#12解决request中getReader()和getInputStream()只能调用一次的问题
目录 1、背景 2、解决方案 2.1、自定义HttpServletRequestWrapper 2.2、JsonRequestHeaderParamsHelper 2.3、HttpServletRequestReplacedFilter 2.4、使用 1、背景 当前系统Content-Type为application/json,参数接收方式采用RequestBody和RequestParam&#…...
直接插入排序+希尔排序+冒泡排序+快速排序+选择排序+堆排序+归并排序+基于统计的排序
插入排序:直接插入排序、希尔排序 交换排序:冒泡排序、快速排序 选择排序:简单选择排序、堆排序 其他:归并排序、基于统计的排序 一、直接插入排序 #include<stdio.h> #include<stdlib.h> /* 直接插入排序&#…...
Java高级 / 架构师 场景方案 面试题(二)
1.双十一亿级用户日活统计如何用 Redis快速计算 在双十一这种亿级用户日活统计的场景中,使用Redis进行快速计算的关键在于利用Redis的数据结构和原子操作来高效地统计和计算数据。以下是一个基于Redis的日活统计方案: 选择合适的数据结构: …...

C/C++内存管理学习【new】
文章目录 一、C/C内存分布二、C语言中动态内存管理方式:malloc/calloc/realloc/free三、C内存管理方式3.1 new/delete操作内置类型3.2 new和delete操作自定义类型四、operator new与operator delete函数五、new和delete的实现原理5.1 内置类型 六、定位new表达式(pl…...

选择适合你的编程语言
引言 在当今瞬息万变的技术领域中,选择一门合适的编程语言对于个人职业发展和技术成长至关重要。每种语言都拥有独特的设计哲学、应用场景和市场需求,因此,在决定投入时间和精力去学习哪种编程语言时,我们需要综合分析多个因素&a…...
【力扣每日一题】力扣106从中序和后序遍历序列构造二叉树
题目来源 力扣106从中序和后序遍历序列构造二叉树 题目概述 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 思路分析 后序遍历序列的最末尾数…...
logback日志回滚原理
日志输出主要依赖RollingFileAppender、TimeBasedRollingPolicy、SizeAndTimeBasedFNATP。 RollingFileAppender 主要用于生成日志文件,格式化内容再输出到日志文件TimeBasedRollingPolicy 设置回滚策略,如果发现日志输出的时间超过单位时间,…...

[C#]winform基于opencvsharp结合pairlie算法实现低光图像增强黑暗图片变亮变清晰
【低光图像增强介绍】 在图像处理领域,低光图像增强是一个具有挑战性的任务。由于光线不足,这些图像往往呈现出低对比度、高噪声和细节丢失等问题,严重影响了图像的视觉效果和后续分析的准确性。因此,开发有效的低光图像增强方法…...

React18源码: reconcliler启动过程
Reconcliler启动过程 Reconcliler启动过程实际就是React的启动过程位于react-dom包,衔接reconciler运作流程中的输入步骤.在调用入口函数之前,reactElement(<App/>) 和 DOM对象 div#root 之间没有关联,用图片表示如下: 在启…...

【RN】为项目使用React Navigation中的navigator
简言 移动应用基本不会只由一个页面组成。管理多个页面的呈现、跳转的组件就是我们通常所说的导航器(navigator)。 React Navigation 提供了简单易用的跨平台导航方案,在 iOS 和 Android 上都可以进行翻页式、tab 选项卡式和抽屉式的导航布局…...

CS50x 2024 - Lecture 8 - HTML, CSS, JavaScript
00:00:00 - Introduction 关于互联网是怎么工作的,如何在他的基础上构建软件 HTML和CSS是描述性语言 javascript一种编程语言,在浏览器上下文中很有用,使得界面更具交互性,也用于服务器 00:01:01 - Bingo Board 00:01:51 - T…...

C++:派生类的生成过程(构造、析构)
目录 派生类的生成过程 派生类的构造函数与析构函数: 构造函数: 派生类组合类的构造和析构: 构造函数和析构函数调用顺序: 派生类的生成过程 三步骤: 吸收基类(父类)成员:实现代…...

金蝶字段添加过滤条件
金蝶字段加过滤条件 F_PLDE_Date<GetValue(FDate) and F_PLDE_Date1>GetValue(FDate)...
SQLite 知识整理
写在前面: 本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。 目录 SQLite 类型数据…...

0基础JAVA期末复习最终版
啊啊啊啊啊啊啊啊啊啊,根据网上各位大佬的复习资料,看了很多大多讲的是基础但对内容的整体把握上缺乏系统了解。但是很不幸最终挂科了,那个出题套路属实把我整神了,所以我决定痛改前非,酣畅淋漓的写下这篇文章。。。。…...

【办公类-16-07-04】合并版“2023下学期 中班户外游戏(有场地和无场地版,一周一次)”(python 排班表系列)
背景需求: 把 无场地版(贴周计划用) 和 有场地版(贴教室墙壁上用) 组合在一起,一个代码生成两套。 【办公类-16-07-02】“2023下学期 周计划-户外游戏 每班1周五天相同场地,6周一次循环”&…...
chat GPT第一讲
计算机的语言奇迹:探秘ChatGPT的智能回答和写作能力 目前我们这个行业,最火的话题无疑是AI人工智能,类似ChatGPT这样的智能Ai,今天剩下的时间不多,每天一个主题,我给大家讲一下计算机回答问题和写作的能力,…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7
在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...

一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...

PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...