Redis篇(缓存机制 - 基本介绍)(持续更新迭代)

news2024/12/21 23:47:15

目录

一、缓存介绍

二、经典三缓存问题

1. 缓存穿透

1.1. 简介

1.2. 解决方案

1.3. 总结

2. 缓存雪崩

2.1. 简介

2.2. 解决方案

2.3. 总结

3. 缓存击穿

3.1. 简介

3.2. 解决方案

3.3. 总结

4. 经典三缓存问题出现的根本原因

三、常见双缓存方案

1. 缓存预热

1.1. 简介

1.2. 作用和目的

2. 缓存清除

2.1. 什么是缓存清除?

2.2. 缓存清除的作用和目的

3. 代码示例

4. 知识小结


一、缓存介绍

缓存是一种数据存储技术,用于存储经常访问的数据,以便在需要时快速获取。通过缓存数据,可以减少

数据的访问时间和系统的负载,从而提高应用程序的性能。缓存可以应用在多个层次,例如CPU缓存、数

据库缓存和Web缓存。

二、经典三缓存问题

1. 缓存穿透

1.1. 简介

缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。

这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空

(相当于进行了两次无用的查询)

这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。

1.2. 解决方案

解决方案:

  • 对空值进行缓存
    类似于上面的例子,虽然数据库中没有id=-9527的用户的数据,但是在redis中对他进行缓存(key=-9527,value=null),这样当请求到达redis的时候就会直接返回一个null的值给客户端,避免了大量无法访问的数据直接打在DB上。
  • 实时监控
    对redis进行实时监控,当发现redis中的命中率下降的时候进行原因的排查,配合运维人员对访问对象和访问数据进行分析查询,从而进行黑名单的设置限制服务。
  • 使用布隆过滤器
    使用BitMap作为布隆过滤器,将目前所有可以访问到的资源通过简单的映射关系放入到布隆过滤器中(哈希计算),当一个请求来临的时候先进行布隆过滤器的判断,如果有那么才进行放行,否则就直接拦截。
  • 接口校验
    类似于用户权限的拦截,对于id=-3872这些无效访问就直接拦截,不允许这些请求到达Redis、DB上。

1.3. 总结

举例:客户端发送大量的不可响应的请求(如下图)

根本原因(结合上文)就是:请求根本不存在的资源

当大量的客户端发出类似于:https://localhost: 9090/user/18933?id=-9527的请求,就可能导致出现

缓存穿透的情况。

因为数据库DB中本身就没有id=-9527的用户的数据,所以Redis也没有对应的数据,那么这些请求在redis

就得不到响应,就会直接打在DB上,导致DB压力过大而卡死情景在线或宕机

2. 缓存雪崩

2.1. 简介

我们可以简单的理解为:由于原有缓存失效,新缓存未到时间(例如:我们设置缓存时采用了相同的过期时

间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库

CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。

2.2. 解决方案

解决方案:

  • 将失效时间分散开
    通过使用自动生成随机数使得key的过期时间是随机的,防止集体过期
  • 使用多级架构
    使用nginx缓存+redis缓存+其他缓存,不同层使用不同的缓存,可靠性更强
  • 设置缓存标记
    记录缓存数据是否过期,如果过期会触发通知另外的线程在后台去更新实际的key
  • 使用锁或者队列的方式
    如果查不到就加上排它锁,其他请求只能进行等待

2.3. 总结

产生的原因:redis中大量的key集体过期

比如:当redis中的大量key集体过期,可以理解为redis中的大部分数据都被清空了(失效了),那么这时

候如果有大量并发的请求来到,那么redis就无法进行有效的响应(命中率急剧下降),请求就都打到DB上

了,到时DB直接崩溃。

3. 缓存击穿

3.1. 简介

某个 key 非常非常热,访问非常的频繁,高并发访问的情况下,当这个 key在失效(可能expire过期了,

也可能LRU淘汰了)的瞬间,大量的请求进来,这时候就击穿了缓存,直接请求到了数据库,一下子来这

么多,数据库肯定受不了,这就叫缓存击穿。某个key突然失效,然后这时候高并发来访问这个key,结果

缓存里没有,都跑到db了。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都

过期了,很多数据都查不到从而查数据库。

3.2. 解决方案

解决方案:

  • 提前对热点数据进行设置
    类似于新闻、某博等软件都需要对热点数据进行预先设置在redis中
  • 监控数据,适时调整
    监控哪些数据是热门数据,实时的调整key的过期时长
  • 使用锁机制
    只有一个请求可以获取到互斥锁,然后到DB中将数据查询并返回到Redis,之后所有请求就可以从Redis中得到响应

3.3. 总结

产生的原因:redis中的某个热点key过期,但是此时有大量的用户访问该过期key。

比如:类似于“某明星出轨事件”上了热搜,这时候大量的“粉丝”都在访问该热点事件,但是可能由于某种原

因,redis的这个热点key过期了,那么这时候大量高并发对于该key的请求就得不到redis的响应,那么就会将请求

直接打在DB服务器上,导致整个DB瘫痪。

4. 经典三缓存问题出现的根本原因

三者出现的根本原因是:Redis缓存命中率下降,请求直接打到DB上了

正常情况下,大量的资源请求都会被redis响应,在redis得不到响应的小部分请求才会去请求DB,这样DB

的压力是非常小的,是可以正常工作的

如果大量的请求在redis上得不到响应,那么就会导致这些请求会直接去访问DB,导致DB的压力瞬间变大

而卡死或者宕机。

大量的高并发的请求打在redis上

这些请求发现redis上并没有需要请求的资源,redis命中率降低

因此这些大量的高并发请求转向DB(数据库服务器)请求对应的资源

DB压力瞬间增大,直接将DB打垮,进而引发一系列“灾害”

三、常见双缓存方案

1. 缓存预热

1.1. 简介

缓存预热是一种在应用程序启动或缓存失效之后,主动将热点数据加载到缓存中的策略。

这样,在实际请求到达应用程序时,热点数据已经存在于缓存中,从而减少了缓存未命中的情况,提高了

应用程序的响应速度。

1.2. 作用和目的

缓存预热的主要作用和目的如下:

  1. 提高缓存命中率:通过预先加载热点数据,缓存预热可以提高缓存的命中率,从而减少对后端数据源(如数据库)的访问,降低系统的负载。
  2. 保持应用程序性能稳定:在应用程序启动或缓存失效之后,缓存预热可以防止请求对后端数据源产生突然的压力,从而保持应用程序的性能稳定。
  3. 优化用户体验:由于热点数据已经存在于缓存中,用户在请求这些数据时能获得更快的响应速度,从而提高用户体验。

2. 缓存清除

2.1. 什么是缓存清除?

缓存清除是一种策略,用于在数据发生变化时删除或更新缓存中的相关数据,以确保缓存中的数据与数据

源保持一致。缓存清除可以是手动触发的,也可以是自动触发的,例如设置缓存的过期时间。

2.2. 缓存清除的作用和目的

缓存清除的主要作用和目的如下:

  1. 保持数据一致性:当数据发生变化时,缓存清除可以确保缓存中的数据与数据源保持一致,从而避免因缓存数据过期或错误而导致的应用程序错误。
  2. 释放缓存空间:缓存空间是有限的,缓存清除可以删除不再需要的数据,为新的数据访问腾出空间。
  3. 提高缓存利用率:通过删除过期或不常用的数据,缓存清除可以确保缓存中的数据是最有价值的,从而提高缓存的利用率。
  4. 避免脏数据:在某些情况下,缓存中的数据可能因为程序错误、系统故障等原因而变得不可靠。
    缓存清除可以定期或根据需要清理这些脏数据,确保缓存中的数据是有效的。

3. 代码示例

我们使用Spring Boot的spring-boot-starter-cache依赖来实现缓存。

首先,在pom.xml中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

假设我们有一个表示商品的Product实体:

public class Product {
    private Long id;
    private String name;
    private BigDecimal price;
 
    // 构造函数、getter和setter方法
}

我们创建一个ProductService类来处理Product实体的查询和更新操作,

并使用@Cacheable和@CacheEvict注解来实现缓存预热和缓存清除。

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
 
import java.util.List;
 
@Service
public class ProductService {
 
    private final ProductRepository productRepository;
 
    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
 
    @Cacheable(value = "products", key = "#id")
    public Product getProduct(Long id) {
        // 模拟数据库查询
        return productRepository.findById(id);
    }
 
    @CacheEvict(value = "products", key = "#product.id")
    public void updateProduct(Product product) {
        // 模拟数据库更新
        productRepository.update(product);
    }
 
    // 缓存预热方法
    public void cacheWarmUp() {
        List<Product> products = productRepository.findAll();
        for (Product product : products) {
            getProduct(product.getId());
        }
    }
}

在这个示例中,我们使用@Cacheable注解来缓存getProduct方法的结果,当获取商品时,首先会在缓存

中查找,如果未找到,则查询数据库并将结果存储到缓存中。我们使用@CacheEvict注解来清除

updateProduct方法更新的商品的缓存。cacheWarmUp方法用于缓存预热,它主动加载所有商品到缓存

中。要在应用程序启动时执行缓存预热,我们可以实现CommandLineRunner接口并重写run方法:

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
 
@Component
public class CacheWarmUpRunner implements CommandLineRunner {
 
    private final ProductService productService;
 
    public CacheWarmUpRunner(ProductService productService) {
        this.productService = productService;
    }
 
    @Override
    public void run(String... args) {
        productService.cacheWarmUp();
    }
}

现在,我们的应用程序在启动时将自动执行缓存预热,加载所有商品到缓存中。

同时,在更新商品时,相关缓存将被清除,以保持数据的一致性。

4. 知识小结

本节详细介绍了缓存预热和缓存清除的概念、原理、作用和目的。缓存预热是一种主动加载热点数据到缓

存的策略,旨在提高缓存命中率、保持应用程序性能稳定和优化用户体验。而缓存清除则是在数据发生变

化时删除或更新缓存中的相关数据,以保持数据一致性、释放缓存空间、提高缓存利用率和避免脏数据。

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

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

相关文章

MQ高级:RabbitMQ小细节

在之前的学习中&#xff0c;我们只介绍了消息的发送&#xff0c;但是没有考虑到异常的情况&#xff0c;今天我们就介绍一些异常情况&#xff0c;和细节的部分。 目录 生产者可靠性 生产者重连 生产者确认 MQ可靠性 持久化 Lazy Queue 消费者可靠性 消费者确认机制 失…

LoadRunner实战测试解析:记录一次性能测试过程

环境准备 PC&#xff1a; Windows7/XP LoadRunner11&#xff1a; 与win10及以上版本不兼容 Nmon&#xff1a; 性能监控工具&#xff0c;部署到被测服务器 LoadRunner破解安装 下载地址&#xff1a;https://pan.baidu.com/s/1WJjcFWhrkWW-GgYwXdEniQ 提取码&#xff1a;f4z…

基于Spark的汽车行业大数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

NetApp 混合闪存 FAS 统一存储平台

挑战 简化内部和公有云中的数据管理 各种规模的企业在精简其存储运维方面正面临越来越大的挑战。他们存储和备份的数据量不断增长&#xff0c;而预算却在缩减。他们需要一个既能满足内部环境要求&#xff0c;又能结合公有云战略的解决方案。 解决方案 兼顾容量与性能的存储&…

设计模式-策略模式-200

优点&#xff1a;用来消除 if-else、switch 等多重判断的代码&#xff0c;消除 if-else、switch 多重判断 可以有效应对代码的复杂性。 缺点&#xff1a;会增加类的数量&#xff0c;有的时候没必要为了消除几个if-else而增加很多类&#xff0c;尤其是那些类型又长又臭的 原始代…

scratch棒球运动 2024年9月中国电子学会图形化编程 少儿编程 scratch编程等级考试一级真题和答案解析

目录 scratch棒球运动 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、 推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、…

进程--信号量

信号量是什么 资源的竞争 资源竞争 : 当多个进程同时访问共享资源时&#xff0c;会产生资源竞争&#xff0c;最终最导致数据混乱临界资源 : 不允许同时有多个进程访问的资源&#xff0c;包括硬件资源(CPU、内存、存储器以及其他外围设备)与软件资源(共享代码段、共享数据结构…

SpringCloudEureka实战:搭建EurekaServer

1、依赖引入 <dependencies><!-- 注册中心 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency> </dependencies> <de…

66.对cplusplus网的strtok函数的详细解释(补第56篇的翻译)

56.【C语言】字符函数和字符串函数(strtok函数) 点我跳转 目录 56.【C语言】字符函数和字符串函数(strtok函数) 点我跳转 1.原文 2. 翻译 1.原文 原文链接: cplusplus的介绍 点我跳转 2. 翻译 函数 strtok char * strtok ( char * str, const char * delimiters ); Spli…

如何构建一个生产级的AI平台(3)?

书接上回&#xff0c;继续往下讲,本节会说一下模型的路由和网关 模型的路由和网关 随着应用程序复杂性的增加和涉及的模型越来越多&#xff0c; 出现了两种类型的工具来帮助使用多个模型&#xff1a;路由和网关 1. 路由 应用程序可以使用不同的模型来响应不同类型的查询。 …

平衡二叉搜索树删除的实现

前言 上期讲了平衡二叉搜索树的插入&#xff0c;这一期我们来讲讲删除。同时&#xff0c;二叉搜索树的简介不会出现在本篇博客之中&#xff0c;如有需要可以查看上一篇博客《平衡二叉搜索树插入的实现》。 平衡二叉搜索树插入的实现-CSDN博客文章浏览阅读659次&#xff0c;点赞…

三、I/O控制器

1.主要功能 接受和识别CPU发出的命令(要有控制寄存器) 向CPU报告设备的状态(要有状态寄存器) 数据交换(要有数据寄存器&#xff0c;暂存输入/输出的数据) 地址识别(由I/0逻辑实现) 2.组成 CPU与控制器之间的接口(实现控制器与CPU之间的通信) I/0逻辑(负责识别CPU发出的命…

鸿蒙NEXT开发-ArkUI(基于最新api12稳定版)

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

自定义注解加 AOP 实现服务接口鉴权以及内部认证

注解 何谓注解&#xff1f; 在Java中&#xff0c;注解&#xff08;Annotation&#xff09;是一种特殊的语法&#xff0c;用符号开头&#xff0c;是 Java5 开始引入的新特性&#xff0c;可以看作是一种特殊的注释&#xff0c;主要用于修饰类、方法或者变量&#xff0c;提供某些信…

中英翻译神器!轻松搞定跨文化沟通

大家好&#xff01;今天咱们来聊聊那些你生活中不可或缺的翻译小助手&#xff1b;不论你是个英语小白&#xff0c;还是希望更快地了解外国文献、掌握外媒信息&#xff0c;或者是从事需要大量翻译工作的小伙伴&#xff0c;总有一款翻译工具能帮你省时省力&#xff0c;让你的生活…

DBCP数据库连接池以及在Tomcat中配置JNDI数据源

前言 数据库连接 数据库连接是指在计算机系统中建立起应用程序与数据库之间的连接通道&#xff0c;用于进行数据的读取和写入操作。通过数据库连接&#xff0c;应用程序可以与数据库进行交互&#xff0c;执行各种数据库操作&#xff0c;如查询数据、插入数据、更新数据和删除数…

算法题总结(四)——螺旋矩阵

螺旋矩阵 59、螺旋矩阵二 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]示例 2&#xff1a; 输…

2.点位管理开发(续)及设计思路——帝可得后台管理系统

目录 前言一、页面原型二、修改1、页面展示2、新增 3 、总结思路 前言 提示&#xff1a;本篇继续点位管理的改造 一、页面原型 页面展示新增 二、修改 1、页面展示 页面修改&#xff1a;修改标签换行、顺序顺序、地址过长时换行问题&#xff1b; <el-table v-loading…

七,MyBatis-Plus 扩展功能:乐观锁,代码生成器,执行SQL分析打印(实操详细使用)

七&#xff0c;MyBatis-Plus 扩展功能&#xff1a;乐观锁&#xff0c;代码生成器&#xff0c;执行SQL分析打印&#xff08;实操详细使用&#xff09; 文章目录 七&#xff0c;MyBatis-Plus 扩展功能&#xff1a;乐观锁&#xff0c;代码生成器&#xff0c;执行SQL分析打印&#…

愿祖国富强!肌肉水凝胶的奥秘,自协调与光驱动,运动模式大揭秘

大家好&#xff0c;在这个国庆佳节&#xff0c;我们一同感受科技的魅力。今天来了解一种特殊的肌肉样水凝胶&#xff0c;它通过自协调形状变化和摩擦调节&#xff0c;能在光的引导下实现多样运动。这一成果为软机器人发展带来新契机——《Light-steered locomotion of muscle-l…