Redis-缓存穿透击穿雪崩
1. 穿透问题
缓存穿透问题就是查询不存在的数据。在缓存穿透中,先查缓存,缓存没有数据,就会请求到数据库上,导致数据库压力剧增。
解决方法:
- 给不存在的key加上空值,防止每次都会请求到数据库。
- 布隆过滤器,做一次过滤
1.1 使用缓存空值解决缓存击穿问题
- 根据id=1来请求
- redis存在数据
2.1. 存储的是空值{},那么返回null
2.2. 存储的不是空值,说明存储的是真实的数据库数据- redis不存在数据
- 查询数据库
4.1. 数据库存在数据,那么缓存数据到redis,返回真实的数据
4.2. 数据库不存在数据,那么缓存空对象 {},设置一个过期时间,返回空
@Component
public class RedisCacheClient {private final StringRedisTemplate stringRedisTemplate;public RedisCacheClient(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}private void set(String key, Object value, Long time, TimeUnit timeUnit) {stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), time, timeUnit);}private String get(String key) {return stringRedisTemplate.opsForValue().get(key);}public <ID, R> R queryWithPassThrough(String keyPrefix, ID id, Class<R> clazz,Function<ID, R> dbFallBack, Long time, TimeUnit unit) {String key = keyPrefix + id;// 1.从redis查询数据String json = get(key);// 2.判断数据是否存在if (RedisConstants.EMPTY_OBJECT_JSON.equals(json)) {return null; //缓存的空对象值}if (StrUtil.isNotEmpty(json)) {return JSONUtil.toBean(json, clazz);}// 3.不存在,根据id查询数据库R r = dbFallBack.apply(id);if (r != null) {set(key, r, time, unit);return r;}// 4.存储空对象set(key, RedisConstants.EMPTY_OBJECT_JSON /*{}*/, RedisConstants.CACHE_NULL_TTL, TimeUnit.SECONDS);return null;}
}
1.2 使用布隆过滤器做初次判断
对于恶意攻击,向服务器请求大量不存在的数据造成的缓存穿透,还可以用布隆过滤器先做一次过滤,对于不存在的数据,布隆过滤器一般都能够过滤掉,不让请求再往后端发送。当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在。

布隆过滤器就是一个大型的位数组和几个不一样的无偏 hash 函数。所谓无偏就是能够把元素的 hash 值算得比较均匀。
向布隆过滤器中添加 key 时,会使用多个 hash 函数对 key 进行 hash 算得一个整数索引值然后对位数组长度 进行取模运算得到一个位置,每个 hash 函数都会算得一个不同的位置。再把位数组的这几个位置都置为 1 就 完成了 add 操作。向布隆过滤器询问 key 是否存在时,跟 add 一样,也会把 hash 的几个位置都算出来,看看位数组中这几个位置是否都为 1,只要有一个位为 0,那么说明布隆过滤器中这个key 不存在。如果都是 1,这并不能说明这个key 就一定存在,只是极有可能存在,因为这些位被置为 1 可能是因为其它的 key 存在所致。如果这个位数组比较稀疏,这个概率就会很大,如果这个位数组比较拥挤,这个概率就会降低。
这种方法适用于数据命中不高、 数据相对固定、 实时性低(通常是数据集较大) 的应用场景, 代码维护较为复杂, 但是缓存空间占用很少。
1.2.1 导入pom坐标
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.13.6</version>
</dependency>
1.2.2 布隆过滤器代码示例
class Main {private RedissonClient redissonClient;void test() {RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("orderList");// 1.初始化布隆过滤器:预计元素为100000000L,误判率为3%,根据这两个参数会计算出底层的bit数组大小bloomFilter.tryInit(100000000L, 0.03);// 2.添加元素到bloomFilterbloomFilter.add("ayuan");// 3.判断下面的数据是否在布隆过滤器中System.out.println(bloomFilter.contains("asheng"));System.out.println(bloomFilter.contains("longge"));System.out.println(bloomFilter.contains("ayuan"));}
}
使用布隆过滤器需要把所有数据提前放入布隆过滤器,并且在增加数据时也要往布隆过滤器里放,布隆过滤器缓存过滤伪代码:

1.2.3 布隆过滤器实战
class Main {@Autowiredprivate RedissonClient redissonClient;private RBloomFilter<String> bloomFilter;@PostConstructvoid init() {// 1.初始化布隆过滤器bloomFilter = redissonClient.getBloomFilter("orderList");// 初始化布隆过滤器:预计元素为100000000L,误判率为3%,根据这两个参数会计算出底层的bit数组大小bloomFilter.tryInit(100000000L, 0.03);// 2.加载所有的数据加载到布隆过滤器// for (String key : keys) {// bloomFilter.add(key);// }}@TestString get(String key) {// 3.从布隆过滤器这一级缓存判断key是否存在boolean isContains = bloomFilter.contains(key);if (!isContains) {return "";}// 4.业务逻辑开发}
}
但是布隆过滤器无法删除某一个元素,如果要删除得重新初始化数据
2. 击穿问题
缓存击穿中,请求的 key 对应的是热点数据 ,该数据存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。这就可能会导致瞬时大量的请求直接打到了数据库上,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。
![[图片]](https://i-blog.csdnimg.cn/direct/5c2b0b7ba7284ef3b2cc862864dc5b00.png)
解决方案:
- 基于互斥锁(看情况):在缓存过期后,通过设置互斥锁确保只有一个请求去查询数据库并且更新缓存。
- 提前预热(推荐):针对热点数据提前预热,并将其入缓存中并设置合理的过期事件,比如:秒杀场景下的数据在秒杀结束前永不过期。
- 数据永不过期(不推荐):设置热点数据永不过期或者过期时间比较长。
2.1 基于互斥锁解决缓存击穿问题
@Component
public class RedisCacheClient {private final StringRedisTemplate stringRedisTemplate;private final RedissonClient redissonClient;public RedisCacheClient(StringRedisTemplate stringRedisTemplate, RedissonClient redissonClient) {this.stringRedisTemplate = stringRedisTemplate;this.redissonClient = redissonClient;}private void set(String key, Object value, Long time, TimeUnit timeUnit) {stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), time, timeUnit);}private String get(String key) {return stringRedisTemplate.opsForValue().get(key);}public <ID, R> R query(String keyPrefix, ID id, Class<R> clazz,Function<ID, R> dbFallBack, Long time, TimeUnit unit) {String key = keyPrefix + id;// 1.从redis查询数据String json = get(key);// 2.判断数据是否存在if (RedisConstants.EMPTY_OBJECT_JSON.equals(json)) {return null; //缓存的空对象值}if (StrUtil.isNotEmpty(json)) {return JSONUtil.toBean(json, clazz);}//加锁,防止缓存击穿问题 -> redis的热点key问题RLock redissonClientLock = redissonClient.getLock(RedisConstants.DISTRIBUTED_LOCK + key);redissonClientLock.lock(); //加锁try {//dcl判断锁是否存在了json = get(key);if (json != null) {return queryWithPassThrough(keyPrefix, id, clazz, dbFallBack, time, unit);}//3. 不存在,根据id查询数据库R r = dbFallBack.apply(id);if (r != null) {set(key, r, time, unit);return r;}// 存储空对象set(key, RedisConstants.EMPTY_OBJECT_JSON, RedisConstants.CACHE_NULL_TTL, TimeUnit.SECONDS);return null;} finally {redissonClientLock.unlock();}}
}
3. 雪崩问题
缓存宕机或者在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力。

解决方式:
- 设置随机失效时间(可选):为缓存设置随机的失效时间,例如在固定过期时间的基础上加上一个随机值,这样可以避免大量缓存同时到期,从而减少缓存雪崩的风险。(例如:批量导入数据到redis的时候,如果设置过期时间一致,那么就会数据就会在同一时刻过期删除)。
- 多级缓存:设计多级缓存,例如本地缓存+Redis 缓存的二级缓存组合,当 Redis 缓存出现问题时,还可以从本地缓存中获取到部分数据。
- Redis集群:采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。比如:Redis Sentinel哨兵集群、Redis Cluster分片集群。
- 限流:如果发现读请求太多,可以采用限流的策略。
相关文章:
Redis-缓存穿透击穿雪崩
1. 穿透问题 缓存穿透问题就是查询不存在的数据。在缓存穿透中,先查缓存,缓存没有数据,就会请求到数据库上,导致数据库压力剧增。 解决方法: 给不存在的key加上空值,防止每次都会请求到数据库。布隆过滤器…...
Windows server网络安全
摘要 安全策略 IP安全策略,简单的来说就是可以通过做相应的策略来达到放行、阻止相关的端口;放行、阻止相关的IP,如何做安全策略,小编为大家详细的写了相关的步骤: 解说步骤: 阻止所有: 打…...
代理(Delegate)、闭包(Closure)、Notification(通知中心) 和 swift_event_bus适用场景和工作方式
在 Swift 开发中,在 Swift 开发中,代理(Delegate)、闭包(Closure)、Notification(通知中心) 和 swift_event_bus 主要用于 组件之间的通信,但它们的适用场景和工作方式有…...
Python从入门到精通1:FastAPI
引言 在现代 Web 开发中,API 是前后端分离架构的核心。FastAPI 凭借其高性能、简洁的语法和自动文档生成功能,成为 Python 开发者的首选框架。本文将从零开始,详细讲解 FastAPI 的核心概念、安装配置、路由设计、请求处理以及实际应用案例&a…...
使用 crontab 定时同步服务器文件到本地
https://www.dong-blog.fun/post/1987 1. 安装 sshpass sshpass 是一个可以自动输入密码的工具。如果未安装,运行以下命令安装: • 对于 Debian/Ubuntu 系统: apt update && apt install sshpass• 对于 CentOS/RHEL 系统…...
Leetcode做题记录----2
1、两数之和 思路: 1、不能使用相同元素,可以想到哈希表,,C#中可以通过字典建立当前值和下标的关系 2、显然,依次判断数组中的每个数即可 3、定义other target - num[ i ] 这个other就是我们用于在字典中进行寻找…...
批量合并 Word 文档,支持合并成一个 Word,也支持按文件夹合并
我们经常会碰到需要将多个 Word 文档批量合并成一个 Word 文档的场景,比如需要合并后打印、合并后方便整理存档等等。如果是人工的操作,会非常的麻烦。因此我们通常会借助一些批量处理脚本或者寻找批量处理的工具来帮我们实现批量合并 Word 文档的操作。…...
项目实操分享:一个基于 Flask 的音乐生成系统,能够根据用户指定的参数自动生成 MIDI 音乐并转换为音频文件
在线体验音乐创作:AI Music Creator - AI Music Creator 体验者账号密码admin/admin123 系统架构 1.1 核心组件 MusicGenerator 类 负责音乐生成的核心逻辑 包含 MIDI 生成和音频转换功能 管理音乐参数和音轨生成 FluidSynth 集成 用于 MIDI 到音频的转换 …...
神经网络为什么要用 ReLU 增加非线性?
在神经网络中使用 ReLU(Rectified Linear Unit) 作为激活函数的主要目的是引入非线性,这是神经网络能够学习复杂模式和解决非线性问题的关键。 1. 为什么需要非线性? 1.1 线性模型的局限性 如果神经网络只使用线性激活函数&…...
RK3568平台(音频篇)AD82584F功放
一.AD82584 功放芯片简介 AD82584 是 Analog Devices 公司推出的一款高性能、多通道音频功率放大器芯片。 它专为汽车音响系统、家庭影院和其他需要高质量音频放大的应用而设计。以下是关于 AD82584 的详细介绍。 Analog Devices 官方网站:https://www.analog.com AD82584…...
动态规划详解(二):从暴力递归到动态规划的完整优化之路
目录 一、什么是动态规划?—— 从人类直觉到算法思维 二、暴力递归:最直观的问题分解方式 1. 示例:斐波那契数列 2. 递归树分析(以n5为例) 3. 问题暴露 三、第一次优化:记忆化搜索(Memoiza…...
ubuntu下在pycharm中配置已有的虚拟环境
作者使用的ubuntu系统位于PC机上的虚拟机。系统版本为: 在配置pycharm解释器之前你需要先创建虚拟环境以及安装pycharm。 作者创建的虚拟环境位于/home/topeet/miniconda3/envs/airproject/,如下图所示: 作者安装的pycharm版本为2023社区…...
虚幻基础:动画层接口
文章目录 动画层:动画图表中的函数接口:名字,没有实现。动画层接口:由动画蓝图实现1.动画层可直接调用实现功能2.动画层接口必须安装3.动画层默认使用本身实现4.动画层也可使用其他动画蓝图实现,但必须在角色蓝图中关联…...
deepseek R1提供的3d迷宫设计方案
一、技术选型方案 核心渲染技术 🎨 采用Raycasting算法模拟3D透视效果使用Canvas 2D上下文进行逐像素绘制材质贴图系统实现墙面差异化表现 迷宫数据结构 🗺️ 二维数组存储迷宫布局(0:通路,1:墙体)递归回溯算法生成随…...
2024华为OD机试真题-日志排序(C++/Java/Python)-E卷-100分
2024华为OD机试最新E卷题库-(C卷+D卷+E卷)-(JAVA、Python、C++) 目录 题目描述 输入描述 输出描述 示例1 示例2 示例3 解题思路 代码 c++ python Java 题目描述 运维工程师采集到某产品现网运行一天产生的日志N条,现需根据日志时间按时间先后顺序对日志进行排序。…...
爬虫中一些有用的用法
文本和标签在一个级别下 如果文本和a标签在一个级别下 比如: # 获取a标签后的第一个文本节点text_node a.xpath(following-sibling::text()[1])[0].strip() 将xpath的html代码转换成字符串 etree.tostring(root, pretty_printTrue, encoding"utf-8")…...
Python控制语句-条件分支-if
1.以下代码的输出结果是()。 for i in range(1,6): if i%4= =0: continue else: print(i, end=“,”) A、1,2,3 B、1,2,3,4 C、1,2,3,5, D、1,2,3,5,6 答案:C。for循环依次将1-6依次赋给i,i从1,2,3,4,5依次变化,当i%4= =0时,结束本次循环进入下一循环;反之输出的值,故输出…...
DeepIn Wps 字体缺失问题
系统缺失字体 Symbol 、Wingdings 、Wingdings2、Wingdings3、MT—extra 字体问题 问了下DeepSeek 在应用商店安装或者在windows 里面找 装了一个GB-18030 还是不行 在windows里面复制了缺失的字体 将字体复制到DeepIn 的字体目录(Ubuntu 应该也是这个目录&am…...
【webrtc debug tools】 rtc_event_log_to_text
一、rtc_event_log 简介 在学习分析webrtc的过程中,发现其内部提供了一个实时数据捕获接口RtcEventLog。通过该接口可以实时捕获进出webrtc的RTP报文头数据、音视频配置参数、webrtc的探测数据等。其内容实现可参考RtcEventLogImpl类的定义。其文件所在路径 loggin…...
数字IC后端项目典型问题(2025.03.10数字后端项目问题记录)
小编发现今天广大学员发过来的问题都比较好,立即一顿输出分享给大家(每天都有好多种类的数字后端问题)。后续可能会经常通过这种方式来做分享。其实很多问题都是实际后端项目中经常遇到的典型问题。希望通过这种方式的分享能够帮助到更多需要…...
我与DeepSeek读《大型网站技术架构》(10)- 维基百科的高性能架构设计分析
目录 网站整体架构核心组件请求处理流程图关键环节说明 性能优化策略前端优化:拦截 80% 以上请求服务端优化:高性能 PHP 集群后端优化:存储与缓存极致设计Memcached 持久化连接 性能优化策略对比表 网站整体架构 核心组件 Wikipedia 的架构…...
Redis 持久化详解:RDB 与 AOF 的机制、配置与最佳实践
目录 引言 1. Redis 持久化概述 1.1 为什么需要持久化? 1.2 Redis 持久化的两种方式 2. RDB 持久化 2.1 RDB 的工作原理 RDB 的触发条件 2.2 RDB 的配置 2.3 RDB 的优缺点 优点 缺点 3. AOF 持久化 3.1 AOF 的工作原理 AOF 的触发条件 3.2 AOF 的配置…...
说一下spring的事务隔离级别?
大家好,我是锋哥。今天分享关于【说一下spring的事务隔离级别?】面试题。希望对大家有帮助; 说一下spring的事务隔离级别? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Spring的事务隔离级别是指在数据库事务管理中…...
Java 大视界 -- 基于 Java 的大数据实时数据处理框架性能评测与选型建议(121)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
深度解读:OpenAI发布GPT-5的技术突破与商业影响
引言 2025年2月,OpenAI正式发布GPT-5,这一被誉为“AI新纪元开篇之作”的模型,不仅实现了技术架构的颠覆性创新,更以免费开放策略引发行业地震。本文将从技术突破、商业影响、行业竞争格局及未来挑战四个维度,全面解析…...
NAT NAPT
NAT NAT(Network Address Translation,网络地址转换) 主要用于在不同网络(如私有网络和公共互联网)之间进行 IP 地址转换,解决IP 地址短缺问题,并提供一定的安全性。 IPv4 地址是 32 位…...
harmonyOS(鸿蒙)— 网络权限(解决app网络资源无法加载,图片无法显示)
harmonyOS系列 harmonyOS(网络权限) 一、问题梳理二、代码及图示 一、问题梳理 在鸿蒙app的开发里会有联网业务无法加载,图片无法显示的情况,多半是系统的网络权限没有申请,所以无法使用需要网络加载的资源࿰…...
Python毕业设计选题:基于django+vue的疫情数据可视化分析系统
开发语言:Python框架:djangoPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 管理员登录 管理员功能界面 用户管理 员工管理 疫情信息管理 检测预约管理 检测结果…...
小程序配置webview
1.在微信公众平台配置业务域名 1)包括把校验文件放在服务器根目录 2)配置域名 2.在小程序中 新建文件 小程序新建页面:web-view json配置:{ "pageOrientation": "landscape", "renderer":&qu…...
清华同方国产电脑能改windows吗_清华同方国产系统改win7教程
清华同方国产电脑能改windows吗?清华同方国产电脑如果采用的是兆芯kx-6000系列或kx-7000系列以及海光c86 3250 3350 X86架构处理器可以安装windows。在安装win7时bios中要关闭“安全启动”和开启legacy传统模式支持,如果是NVME接口的固态硬盘,…...
