14、缓存预热+缓存雪崩+缓存击穿+缓存穿透
缓存预热+缓存雪崩+缓存击穿+缓存穿透
● 缓存预热、雪崩、穿透、击穿分别是什么?你遇到过那几个情况?
● 缓存预热你是怎么做到的?
● 如何避免或者减少缓存雪崩?
● 穿透和击穿有什么区别?它两一个意思还是截然不同?
● 穿透和击穿你有什么解决方案?如何避免?
● 加入出现了缓存不一致,你有哪些修补方案?
1、缓存预热
2、缓存雪崩
发生原因
● Redis主机挂了,Redis全盘崩溃,偏硬件运维。
● Redis中有大量key同时过期大面积失效,偏软件开发。
预防+解决
● Redis中key设置为永不过期or过期时间错开
● Redis缓存集群实现高可用
○ 主从+哨兵
○ Redis Cluster
○ 开启Redis持久化机制RDB/AOF,尽快恢复缓存集群
● 多缓存结合预防雪崩
○ ehcache本地缓存+redis缓存
● 服务降级
○ Hystrix或者案例sentinel限流&降级
3、缓存穿透
发生原因
请求去查一条记录,先查Redis无,后查MySQL无,都查不到该条记录,但是请求每次都会打到数据库上面去,导致后台数据库压力暴增,这种就是缓存穿透。
简单来说就是本来无一物,两库都没有,既不在Redis缓存库,也不再MySQL,数据库存在被多次暴击风险
解决方案
方案一:空对象缓存或者缺省值
一般正常情况下使用回写增强:mysql也查不到的话就让redis存入刚刚查不到的key并保护mysql,第一次来查询没有查询到,redis和mysql都没有,返回null给调用者,但是增强回写后第二次查同样的key,此时redis就有值了,可以直接从redis中读取default缺省值返回给业务程序,避免了把大量请求发送给mysql处理,打爆mysql------------>此种方法架不住黑客的恶意攻击,有缺陷…只能解决key相同的情况。
黑客或者恶意攻击:黑客会对你的系统进行攻击,拿一个不存在的id去查询数据,会产生大量的请求到数据库查询,可能会导致你的数据库由于压力过大而宕机。
key相同—>第一次达到mysql,空对象缓存后第二次就返回default缺省值,避免mysql再被攻击,不用再到数据库中走一圈了。
key不同—>由于存在空对象缓存和缓存回写(看自己的业务),redis中无关紧张的key也会越来越多(记得设置redis过期时间)。
方案二:Google布隆过滤器Guava解决缓存穿透
Guava中布隆过滤器的实现算是比较权威的,所以实际项目中可以直接采用Guava布隆过滤器
白名单过滤器实战
白名单那过滤器架构说明
误判问题:概率小还可以接受,不能从布隆过滤器中删除
全部合法的key都需要放入Guava版布隆过滤器+Redis里面,不然数据就是返回null
改POM
<!-- Guava Google开源的Guava中自带的布隆过滤器--><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>23.0</version></dependency>
业务类
我们的目的是再白名单里面设置100w的数据,然后再额外加入10w的数据,看一下误判率是多少
/*** @author Guanghao Wei* @create 2023-04-25 14:51*/
@Service
@Slf4j
public class GuavaWithBloomFilterService {//定义常量public static final int _1W = 10000;//定义guava布隆过滤器初始容量public static final int SIZE = 100 * _1W;//误判率,它越小,误判个数越少public static double fpp = 0.03;//创建guava布隆过滤器private BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), SIZE, fpp);public void guavaBloomFilter() {//先让bloomFilter加入100w数据for (int i = 1; i <= SIZE; i++) {bloomFilter.put(i);}//故意取10w个不在合法范围内的数据ArrayList<Object> list = new ArrayList<>(10 * _1W);//验证for (int i = SIZE + 1; i <= SIZE + (10 * _1W); i++) {if (bloomFilter.mightContain(i)) {log.info("被误判了:{}", i);list.add(i);}}log.info("误判总数量:{}", list.size());}
}
/*** @author Guanghao Wei* @create 2023-04-25 14:51*/
@Api(tags = "google工具Guava处理布隆过滤器")
@RestController
@Slf4j
public class GuavaWithBloomFilterController {@Autowiredprivate GuavaWithBloomFilterService guavaWithBloomFilterService;@ApiOperation("guava布隆过滤器插入100万样本数据并额外添加10w测试是否存在")@GetMapping("guavafilter")public void guavaBloomFilter() {guavaWithBloomFilterService.guavaBloomFilter();}
}
这里有一个误判率的知识点我们通过debug源码来学习:
布隆过滤器说明
缓存击穿
是什么
大量的请求同时查询一个key时,此时这个key正好失效了,就会导致大量的请求都打到数据库上去
简单来说就是热点key突然失效了,暴打mysql。
穿透和击穿,截然不同
热点key为什么失效?
时间到了自然清除但还未被访问到
delete掉的key,刚巧又被访问
危害
会造成某一时刻数据库请求量过大,压力剧增
一般技术部门需要知道热点key是哪些,做到心里有数防止击穿
解决
方案一:差异失效时间
对于访问频繁的热点key,干脆就不设置过期时间
方案二:互斥更新
采用双检加锁策略
案例
天猫聚划算功能实现+防止缓存击穿
数据类型可以选用list和zset,但这类场景一般还是选择list
实体类
/*** @author Guanghao Wei* @create 2023-04-25 15:40*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "聚划算活动product信息")
public class Product {private Long id;private String name;private Integer price;private String detail;
}
service
/*** @author Guanghao Wei* @create 2023-04-25 15:42*/
@Service
@Slf4j
public class JHSTaskService {public static final String JHS_KEY = "jhs";public static final String JHS_KEY_A = "jhs:a";public static final String JHS_KEY_B = "jhs:b";@Autowiredprivate RedisTemplate redisTemplate;/*** 模拟从数据库读取20件特价商品,用于加载到聚划算的页面中** @return*/private List<Product> getProductsFromMysql() {List<Product> list = new ArrayList<>();for (int i = 1; i <= 20; i++) {Random random = new Random();int id = random.nextInt(10000);Product obj = new Product((long) id, "product" + i, i, "detail");list.add(obj);}return list;}@PostConstructpublic void init() {log.info("启动定时器天猫聚划算功能模拟开始.........O(∩_∩)O");//用线程模拟定时任务,后台任务定时将mysql里面的参加活动的商品刷进redisnew Thread(() -> {//模拟从mysql查出数据用于加载进redis,在页面展示List<Product> productList = this.getProductsFromMysql();//采用redis list数据结构的lpush命令来存储redisTemplate.delete(JHS_KEY);//加入最新的数据redisTemplate.opsForList().leftPushAll(JHS_KEY, productList);//暂停1分钟,间隔一分钟执行一次,模拟聚划算一天执行的参加活动的品牌try { TimeUnit.MINUTES.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }}, "t1").start();}
}
controller
/*** @author Guanghao Wei* @create 2023-04-25 15:42*/
@Api(tags = "聚划算页面展示控制器")
@RestController
@Slf4j
public class JHSProductController {public static final String JHS_KEY = "jhs";@Autowiredprivate RedisTemplate redisTemplate;/*** 分页查询,在高并发的情况下,只能走Redis查询,走db的话必定会吧db打垮** @param page* @param size* @return*/@ApiOperation("聚划算案例,每次1页展示5条数据")@GetMapping("product/find")public List<Product> find(int page, int size) {List<Product> list = null;long start = (page - 1) * size;long end = start + size - 1;try {list = redisTemplate.opsForList().range(JHS_KEY, start, end);if (CollectionUtils.isEmpty(list)) {//走数据库查询 TODO}log.info("参加活动的商家:{}",list);} catch (Exception e) {//出异常了,一般redis宕机了,或者redis网络抖动导致timeoutlog.error("jhs exception:{}",e);e.printStackTrace();//再次查询}return list;}}
至此步骤,上述聚划算的功能算是完成了,请思考在高并发情况下又会产生什么样的经典生产问题?
Bug和隐患说明
热点key突然失效导致可怕的缓存击穿:delete命令执行的一瞬间有空隙,其他请求线程找Redis为null,达到mysql,暴击mysql…
复习again
最终目的:2条命令原子性是其次的,主要是防止热点key突然失效暴击mysql打爆系统。
进一步升级加固案例
互斥更新—>双检加锁策略
差异失效时间,在本案例中给我们使用这个方式
@PostConstructpublic void initJHSAB() {log.info("启动AB定时器天猫聚划算功能模拟开始.........O(∩_∩)O" + DateUtil.now());//用线程模拟定时任务,后台任务定时将mysql里面的参加活动的商品刷进redisnew Thread(() -> {//模拟从mysql查出数据用于加载进redis,在页面展示List<Product> productList = this.getProductsFromMysql();//先更新B缓存,且让B过期时间超过A,B做兜底redisTemplate.delete(JHS_KEY_B);redisTemplate.opsForList().leftPushAll(JHS_KEY_B, productList);redisTemplate.expire(JHS_KEY_B, 86410L, TimeUnit.SECONDS);//在更新A缓存redisTemplate.delete(JHS_KEY_A);redisTemplate.opsForList().leftPushAll(JHS_KEY_A, productList);redisTemplate.expire(JHS_KEY_A, 86400L, TimeUnit.SECONDS);//暂停1分钟,间隔一分钟执行一次,模拟聚划算一天执行的参加活动的品牌try { TimeUnit.MINUTES.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }}, "t1").start();}
@ApiOperation("AB双缓存架构,防止热点key突然失效")@GetMapping("product/findAB")public List<Product> findAB(int page, int size) {List<Product> list = null;long start = (page - 1) * size;long end = start + size - 1;try {list = redisTemplate.opsForList().range(JHS_KEY_A, start, end);if (CollectionUtils.isEmpty(list)) {log.info("-------A缓存已经失效或者过期了,记得人工修改,B缓存继续顶着");list = redisTemplate.opsForList().range(JHS_KEY_B, start, end);if (CollectionUtils.isEmpty(list)) {//TODO 走数据库查询}}} catch (Exception e) {//出异常了,一般redis宕机了,或者redis网络抖动导致timeoutlog.error("jhs exception:{}", e);e.printStackTrace();//再次查询}return list;}
相关文章:

14、缓存预热+缓存雪崩+缓存击穿+缓存穿透
缓存预热缓存雪崩缓存击穿缓存穿透 ● 缓存预热、雪崩、穿透、击穿分别是什么?你遇到过那几个情况? ● 缓存预热你是怎么做到的? ● 如何避免或者减少缓存雪崩? ● 穿透和击穿有什么区别?它两一个意思还是截然不同&am…...

【PostGreSQL】PostGreSQL到Oracle的数据迁移
项目需要,有个数据需要导入,拿到手一开始以为是mysql,结果是个PostGreSQL的数据,于是装数据库,但这个也不懂呀,而且本系统用的Oracle,于是得解决迁移转换的问题。 总结下来两个思路。 1、Postg…...

jupyter notebook出现ERR_SSL_VERSION_OR_CIPHER_MISMATCH解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

前端进阶Html+css10----定位的参照对象(高频面试题)
1.relative的参照对象 1)元素按照标准流进行排布; 2)定位参照对象是元素自己原来的位置,可以通过left、right、top、bottom来进行位置调整; 2.absolute(子绝父相) 1)元素脱离标准流…...

总结记录Keras开发构建神经网络模型的三种主流方式:序列模型、函数模型、子类模型
Keras是一个易于使用且功能强大的神经网络建模库,它是基于Python语言开发的。Keras提供了高级API,使得用户能够轻松地定义和训练神经网络模型,无论是用于分类、回归还是其他任务。 Keras的主要特点如下: 简单易用:Kera…...
python环境建设
1. 查看通过pip安装包的路径 问题:devchat vscode中配置需要查找devchat的安装路径,使用pip相关的命令查看 pip list | grep package_name 命令显示获取已安装包的信息(包名与版本号)pip show package_name命令能显示该安装的包…...
Python学习笔记第五十九天(Matplotlib 安装)
Python学习笔记第五十九天 Matplotlib 安装后记 Matplotlib 安装 本章节,我们使用 pip 工具来安装 Matplotlib 库,如果还未安装该工具,可以参考 Python pip 安装与使用。 如果您还没有安装Matplotlib,您可以按照以下步骤在Pytho…...

(6)(6.3) 自动任务中的相机控制
文章目录 前言 6.3.1 概述 6.3.2 自动任务类型 6.3.3 创建合成图像 前言 本文介绍 ArduPilot 的相机和云台命令,并说明如何在 Mission Planner 中使用这些命令来定义相机勘测任务。这些说明假定已经连接并配置了相机触发器和云台(camera trigger and gimbal ha…...
什么是cssreset ?为什么要用到cssreset?
1,什么是cssreset ? 顾名思义,css reset,样式重置。即重新设置界面的样式。 CSS reset,又叫做 CSS 重写或者 CSS 重置,用于改写HTML标签的默认样式。 有些HTML标签在浏览器里有默认的样式,例如 p 标签有上…...

SpringCloud学习笔记(四)_ZooKeeper注册中心
基于Spring Cloud实现服务的发布与调用。而在18年7月份,Eureka2.0宣布停更了,将不再进行开发,所以对于公司技术选型来说,可能会换用其他方案做注册中心。本章学习便是使用ZooKeeper作为注册中心。 本章使用的zookeeper版本是 3.6…...

【算法专题突破】双指针 - 移动零(1)
目录 写在前面 1. 题目解析 2. 算法原理 3. 代码编写 写在最后: 写在前面 在进行了剑指Offer和LeetCode hot100的毒打之后, 我决心系统地学习一些经典算法,增强我的综合算法能力。 1. 题目解析 题目链接:283. 移动零 - 力…...

Nginx高可用集群
目录 一.简介二.案例1.实现思路2.配置文件修改3.实现效果故障转移机制 一.简介 以提高应用系统的可靠性,尽可能地减少中断时间为目标,确保服务的连续性,达到高可用的容错效果。例如“故障切换”、“双机热备”、“多机热备”等都属于高可用集…...
Rust 基础入门 ——所有权 引言 :垃圾自动回收机制的缺陷。
在以往,内存安全几乎都是通过 GC 的方式实现,但是 GC 会引来性能、内存占用以及 Stop the world 等问题,在高性能场景和系统编程上是不可接受的, 我们先介绍一下这些概念都是什么: 内存安全是指程序在运行过程中不会访…...

Ubuntu20.04安装软件报错:The following packages have unmet dependencies
Ubuntu20.04更换阿里云源后安装软件都会报错:The following packages have unmet dependencies 查看资料,大概是ubuntu本身的源比较版本较老,而阿里云的源比较新,因此版本不匹配造成依赖的库不匹配,所以只要将阿里云的…...
Java 与设计模式(12):享元模式
一、定义 享元模式是一种结构型设计模式,旨在有效地共享对象以减少内存使用和提高性能。该模式的核心思想是通过共享尽可能多的相似对象来减少内存占用。它将对象分为可共享的内部状态和不可共享的外部状态。内部状态是对象的固有属性,可以在多个对象之…...
React配置代理(proxy)
使用axios进行请求,而配置代理过程。 第一种 在package.json中,添加proxy配置项,之后所有的请求都会指向该地址 但这种方法只能配置一次,也只有一个 示例: "proxy":"https://localhost:5000" 添加后&am…...

队列(Queue):先进先出的数据结构队列
栈与队列https://blog.csdn.net/qq_45467165/article/details/127958960?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22127958960%22%2C%22source%22%3A%22qq_45467165%22%7D 队列(Queue)是一种常见的线…...

CentOS ens160 显示disconnected
使用nmcli device查看网卡状态,显示如图: 检查宿主机系统VMware DHCP Sevice和VMware NAT Sevice服务是否正常运行。 右键点击我的电脑管理按钮,打开计算机管理点击服务...

使用 ChatGPT 创建 PowerPoint 演示文稿
让 ChatGPT 成为您的助手来帮助您编写电子邮件很简单,因为众所周知,它非常能够生成文本。很明显,ChatGPT 无法帮助您做饭。但您可能想知道它是否可以生成文本以外的其他内容。在上一篇文章中,您了解到 ChatGPT 只能通过中间语言为您生成图形。在这篇文章中,您将了解使用中…...

matlab将数组值划分为两类
例如:大于0的处理为1,小于0的处理为-1. 当然,可以选择循环结构和选择结构,但是效率会很低。 这里直接使用逻辑语句完成。 % 不使用循环语句,将数组内值划分为两类 clc; clearvars; a[-0.1422 , -0.0433 , 0.1131 …...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...