redis之缓存预热,缓存雪崩,缓存击穿,缓存穿透

目录

redis缓存预热

redis缓存雪崩

redis缓存击穿

redis缓存穿透


redis缓存预热

        Redis 缓存预热是指在系统启动或者缓存失效后,提前将部分数据加载到 Redis 缓存中,以便用户在访问时能够快速获取数据,提高系统性能和响应速度。

  • 全量加载: 在系统启动时,将所有需要缓存的数据从数据库或其他数据源加载到 Redis 中,确保缓存中包含了所有可能被访问的数据。这种方式适用于数据量较小、变动频率低的场景。

  • 按需加载: 根据访问模式和数据访问频率,预先加载部分热门数据到 Redis 缓存中,以及时满足用户请求。这种方式适用于数据量较大、热点数据集中的场景。

  • 定时加载: 设置定时任务,在系统空闲时段或低峰期,定期从数据库加载数据到 Redis 缓存中,以确保缓存数据的及时性和完整性。

  • 异步加载: 在系统启动后,通过异步任务的方式逐步将数据加载到 Redis 缓存中,避免系统启动时的压力过大。

redis缓存雪崩

        缓存雪崩是指在某个时间段,缓存中大量的数据同时失效或者因为某种原因都不可用,导致大量请求直接落到了后端数据库上,压力过大而导致数据库或其他服务崩溃,最终影响整个系统的稳定性和可用性。

缓存雪崩一般发生在以下情况:

  • 缓存服务器宕机或故障
  • 所有缓存数据在同一时间失效
  • 缓存数据没有设置过期时间或者过期时间过短
  • 大量请求访问热门数据,导致缓存击穿,无法承受巨大的并发请求

避免缓存雪崩,可以采取以下措施:

  • 分布式缓存: 将缓存分散到多个节点上,避免所有节点同时失效导致缓存雪崩。比如使用 Redis Cluster、Memcached Cluster 等分布式缓存方案。

  • 缓存预热: 在系统启动时,预先将热门数据加载到缓存中,避免缓存全部失效时,大量请求落到数据库上。

  • 设置过期时间: 设置合理的缓存过期时间,避免所有缓存同时失效。

  • 限流降级: 当请求量超过系统承受范围时,通过限流或者降级等措施,分流请求,保证系统的稳定性和可用性。

  • 多级缓存: 使用多级缓存架构,将热门数据放到内存中的缓存,避免频繁读取数据库和外部接口。

redis缓存击穿

        缓存击穿是指当某个热点数据的缓存过期或不存在时,大量请求同时访问该数据,导致请求直接落到了后端数据库上,造成数据库压力过大,影响系统性能和可用性。

缓存击穿一般发生在以下情况:

  • 热点数据缓存失效:由于缓存的过期时间到达或被手动删除等原因,导致热点数据不再存在于缓存中。
  • 并发请求访问热点数据:大量并发请求同时访问热点数据,此时缓存未命中,导致请求直接访问数据库。

为了避免缓存击穿,可以采取以下措施:

  1. 加锁机制: 当检测到缓存失效时,先进行加锁操作,只允许一个请求去查询数据库,其他请求等待结果。查询完毕后,更新缓存并释放锁,其他请求再从缓存获取数据。

  2. 设置短暂的空值缓存: 在缓存失效时,先将空值(null)或者占位数据设置到缓存中,并给予较短的过期时间,避免大量请求同时访问数据库。同时,在缓存中设置一个较长的过期时间,以防止后续请求再次击穿。

  3. 异步更新缓存: 当检测到缓存失效后,异步更新缓存,而不是在请求时即时更新缓存。这样可以避免大量请求同时访问数据库,在缓存更新完成后,后续请求再从缓存获取数据。

  4. 使用互斥锁或分布式锁: 在多服务器环境下,使用互斥锁或者分布式锁来保证只有一个请求去查询数据库,其他请求等待结果,避免大量请求同时访问数据库。

redis缓存穿透

        缓存穿透是指恶意请求或者不存在的数据被请求,导致缓存无法命中,每次请求都直接访问数据库或其他数据源,造成数据库压力过大。

缓存穿透一般发生在以下情况:

  • 恶意请求:恶意用户发送的请求,例如使用遍历查询参数、非法字符等,导致缓存无法命中,直接访问数据库。
  • 数据不存在:请求查询的数据本身就不存在于数据库或其他数据源中,无论怎样的请求都无法在缓存中命中。

为了避免缓存穿透,可以采取以下措施:

  1. 布隆过滤器(Bloom Filter): 使用布隆过滤器来预先过滤掉不存在的数据,当请求到来时,首先经过布隆过滤器的检查,如果不在布隆过滤器中,则直接拒绝请求,避免直接访问数据库。

  2. 空对象缓存: 当查询数据库为空时,在缓存中设置一个空对象(如null),并设置较短的过期时间,避免下次请求再次穿透到数据库。

  3. 合法性检查: 对于用户发送的请求参数进行合法性检查,避免恶意请求导致缓存穿透,可以使用验证 token、接口鉴权等方式进行有效性验证。

  4. 限流和监控: 对请求进行限流,避免大量的恶意请求进入系统,同时建立监控系统,及时发现异常请求并进行处理。

 

空对象缓存解决缓存穿透

    public Customer findCustomerById(Integer customerId) {Customer customer = null;// 缓存redis的key名称String key = CACHE_KEY_CUSTOMER + customerId;// 1.去redis上查询customer = (Customer) redisTemplate.opsForValue().get(key);// 2. 如果redis有,直接返回  如果redis没有,在mysql上查询if (customer == null) {// 3.对于高QPS的优化,进来就先加锁,保证一个请求操作,让外面的redis等待一下,避免击穿mysql(大公司的操作 )synchronized (CustomerService.class) {// 3.1 第二次查询redis,加锁后customer = (Customer) redisTemplate.opsForValue().get(key);// 4.再去查询我们的mysqlcustomer = customerMapper.selectByPrimaryKey(customerId);// 5.mysql有,redis无if (customer != null) {// 6.把mysql查询到的数据会写到到redis, 保持双写一致性  7天过期redisTemplate.opsForValue().set(key, customer, 7L, TimeUnit.DAYS);}else {// defaultNull 规定为redis查询为空、MySQL查询也没有,缓存一个defaultNull标识为空,以防缓存穿透redisTemplate.opsForValue().set(key, "defaultNull", 7L, TimeUnit.DAYS);}}}return customer;}

Google布隆过滤器Guava解决缓存穿透

添加pom文件

        <!--guava Google 开源的 Guava 中自带的布隆过滤器--><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>23.0</version></dependency>

业务类

  • GUavaBloomFilterController
import com.xfcy.service.GuavaBloomFilterService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@Api(tags = "gogle工具Guava处理布隆过滤器")
@RestController
@Slf4j
public class GuavaBloomFilterController {@Resourceprivate GuavaBloomFilterService guavaBloomFilterService;@ApiOperation("guava布隆过滤器插入100万样本数据,额外10w(110w)测试是否存在")@RequestMapping(value = "/guavafilter", method = RequestMethod.GET)public void guavaBloomFilter() {guavaBloomFilterService.guavaBloomFilter();}
}
  • GUavaBloomFilterService 
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import java.util.ArrayList;@Slf4j
@Service
public class GuavaBloomFilterService {// 1.定义一个常量public static final int _1W = 10000;// 2.定义我们guava布隆过滤器,初始容量public static final int SIZE = 100 * _1W;// 3.误判率,它越小误判的个数也越少(思考:是否可以无限小? 没有误判岂不是更好)public static double fpp = 0.01;  // 这个数越小所用的hash函数越多,bitmap占用的位越多  默认的就是0.03,5个hash函数   0.01,7个函数// 4.创建guava布隆过滤器private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), SIZE, fpp);public void guavaBloomFilter() {// 1.先让bloomFilter加入100w白名单数据for (int i = 0; i < SIZE; i++) {bloomFilter.put(i);}// 2.故意取10w个不在合法范围内的数据,来进行误判率的演示ArrayList<Integer> list = new ArrayList<>(10 * _1W);// 3.验证for (int i = SIZE + 1; i < SIZE + (10 * _1W); i++){if (bloomFilter.mightContain(i)){log.info("被误判了:{}", i);list.add(i);}}log.info("误判总数量:{}", list.size());}
}

 

缓存问题总结

缓存问题产生原因解决方案
缓存更新不一致数据变更、缓存时效性同步更新、失效更新、异步更新、定时更新
缓存不一致同步更新失败、异步更新增加重试、补偿任务、最终一致
缓存穿透恶意攻击空对象缓存、bloomFilter 过滤器
缓存击穿热点key失效互斥更新、随即退避、差异失效时间
缓存雪崩缓存挂掉快速失败熔断、主从模式、集群模式

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

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

相关文章

HDR 摄影

HDR 摄影&#xff0c;即高动态范围 High Dynamic Range摄影&#xff0c;旨在通过合并不同曝光值的照片来捕捉场景中从最亮到最暗部分的全部细节。 这种技术对于在一个图像中展现广泛的亮度范围特别有用&#xff0c;尤其是在自然光线条件下&#xff0c;如直射日光或阴影区域&…

【Spring MVC篇】返回响应

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Spring MVC】 本专栏旨在分享学习Spring MVC的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、返回静态页面…

嵌入式CAN通信协议原理(下)

本篇文章结合实际CAN控制器继续介绍协议相关的内容&#xff0c;还有示例讲解。 好了&#xff0c;继续吧&#xff01; 二. STM32 CAN 控制器介绍 STM32 的芯片中具有 bxCAN 控制器 (Basic Extended CAN)&#xff0c;它支持 CAN 协议 2.0A 和 2.0B 标准。 该 CAN 控制器支持最…

QT 工具栏 状态栏 停靠部件 核心部件

添加/删除工具栏 删除工具栏方法和删除菜单栏方法一样&#xff0c;不过工具栏可以有多个&#xff0c;所以每次右键MainWindow对象&#xff0c;都可以看到添加工具栏的选项。 工具栏添加动作 新添加的QAction对象会在动作编辑器里找到&#xff08;Action Editor&#xff09;&a…

FastAI 之书(面向程序员的 FastAI)(一)

原文&#xff1a;www.bookstack.cn/read/th-fastai-book 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 序言 原文&#xff1a;www.bookstack.cn/read/th-fastai-book/README.md 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 在很短的时间内&#xff0c;深度…

STM32 I2C

目录 I2C通信 软件I2C读写MPU6050 I2C通信外设 硬件I2C读写MPU6050 I2C通信 R/W&#xff1a;0写1读 十轴&#xff1a;3轴加速度&#xff0c;3轴角速度&#xff0c;3轴磁场强度和一个气压强度 软件I2C读写MPU6050 MyI2C.c #include "stm32f10x.h" …

Vue2学习第一天

Vue2 学习第一天 1. 什么是 vue? Vue 是一套用于构建用户界面的渐进式框架。 2. vue 历史 vue 是在 2013 年创建的&#xff0c;vue3 是 2020 出现的&#xff0c;现在主要是用 vue2&#xff0c;创新公司用的是 vue3 vue 的作者是尤雨溪&#xff0c;vue 的搜索热度比 react…

基于HTML5实现动态烟花秀效果(含音效和文字)实战

目录 前言 一、烟花秀效果功能分解 1、功能分解 2、界面分解 二、HTML功能实现 1、html界面设计 2、背景音乐和燃放触发 3、燃放控制 4、对联展示 5、脚本引用即文本展示 三、脚本调用及实现 1、烟花燃放 2、燃放响应 3、烟花canvas创建 4、燃放声音控制 5、实际…

鸿蒙开发系列教程(十八)--页面内动画(1)

页面内的动画 显示动画 语法&#xff1a;animateTo(value: AnimateParam, event: () > void): void 第一个参数指定动画参数 第二个参数为动画的闭包函数。 如&#xff1a;animateTo({ duration: 1000, curve: Curve.EaseInOut }, () > {动画代码}&#xff09; dura…

Excel导入预览与下载

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Excel导入预览与下载 preview Controller PostMapping("preview")ApiOperation("上传拒付预警预览")public Result<List<ResChargebackWa…

Linux系统编程(四)进程

一、进程的产生&#xff08;fork&#xff09; fork(2) 系统调用会复制调用进程来创建一个子进程&#xff0c;在父进程中 fork 返回子进程的 pid&#xff0c;在子进程中返回 0。 #include <sys/types.h> #include <unistd.h>pid_t fork(void); fork 后子进程不继…

【MySQL】高度为2和3时B+树能够存储的记录数量的计算过程

文章目录 题目答案高度为2时的B树高度为3时的B树总结 GPT4 对话过程 题目 InnoDB主键索引的Btree在高度分别为 2 和 3 时&#xff0c;可以存储多少条记录&#xff1f; 答案 高度为2时的B树 计算过程&#xff1a; 使用公式 ( n 8 ( n 1 ) 6 16 1024 ) (n \times 8 …