【Redis】什么是Redis缓存 雪崩、穿透、击穿?(一篇文章就够了)

目录

什么是Redis?

Redis的正常存储流程?

什么是Redis缓存雪崩?

缓存雪崩

缓存预热

缓存失效时间的随机性

什么是Redis缓存穿透?

缓存穿透

缓存空对象

BloomFilter(布隆过滤器)

什么是Redis缓存击穿?

缓存击穿

互斥锁

逻辑过期时间


什么是Redis?

        Redis:是一种高性能开源的基于内存的,采用键值对存储的非关系型数据库,不保证数据的ACID特性【事务一旦提交,都不会进行回滚】

        采用键值对存储数据在内存或磁盘中,可以对关系型数据库起到补充作用,同时支持持久化[可以将数据保存在可掉电设备中],可以将数据同步保存到磁盘。

说Redis很快是相对于关系型数据库如mysql来说的,主要有以下因素

    第一,数据结构简单,所以速度快【采用键值对的方式】;

    第二,基于内存进行存储,不需要存储数据库,所以速度快;

    第三,采用多路IO复用模型,减少网络IO的时间消耗,避免大量的无用操作,所以速度快;

    第四,单线程避免了线程切换和上下文切换产生的消耗,所以速度快;

Redis的正常存储流程?

        正常流程:当用户访问服务端时,服务端会去访问Redis缓存中是否有该数据的缓存,如果有,就直接返回;如果没有,就去数据库进行查询;查询到结果过后直接返回给客户端,并且将查询的结果数据同步到redis缓存当中。

 

什么是Redis缓存雪崩?

缓存雪崩

        是指在某一时刻缓存中的存储的数据同时大量地失效,而且这些数据都是经常被访问的数据(比如热点文章,热门商品等),这样就会导致大量的请求都会落到数据库上,造成数据库的压力瞬间增大,从而导致服务器宕机,形成一种“雪崩”效应。

        简单来说,就是大量的redis同一时间大面积的失效,大量的请求直接打到数据库上(导致数据库压力飙升),这种现象就是缓存雪崩。

        解决缓存雪崩的方法有很多,其中一种比较常见的方法是采用“缓存预热”和“缓存失效时间的随机性”两种手段来解决。

缓存预热

        是指系统上线后,将相关的缓存数据直接加载到缓存中,这样一来,第一个请求过来的时候,就可以直接在缓存中获取到数据,而不需要去数据库中查询。

缓存失效时间的随机性

        是指在设置缓存的失效时间时,不能够将所有缓存的失效时间都设置为相同的值,而是要在一个合理的时间范围内进行随机,这样可以避免缓存在某一时刻大量失效的情况。

下面是一个采用了缓存预热和缓存失效时间的随机性的Java代码:

public class UserService {

    private static final Random RANDOM = new Random();

    private RedisTemplate<String, User> redisTemplate;

    //可以将所有的初始化需要执行的代码放在一个单独的类中,使用@Scheduled或quartz或xxl-job定时控制执行
    public UserService(RedisTemplate<String, User> redisTemplate) {
        this.redisTemplate = redisTemplate;
        // 缓存预热,将所有用户数据加载到缓存中
        List<User> users = getUsersFromDB();
        for (User user : users) {
            redisTemplate.opsForValue().set(user.getId(), user, getExpireTime());
        }
    }

    public User getUser(String userId) {
        // 先从缓存中获取数据
        User user = redisTemplate.opsForValue().get(userId);
        if (user != null) {
            return user;
        }
        // 缓存中没有数据,则从数据库中查询
        user = getUserFromDB(userId);
        if (user != null) {
            // 将数据放入缓存,并且设置一个随机的失效时间
            redisTemplate.opsForValue().set(userId, user, getExpireTime());
        }
        return user;
    }

    private List<User> getUsersFromDB() {
        // 从数据库中查询所有用户数据
        // ...
    }

    private User getUserFromDB(String userId) {
        // 从数据库中查询用户数据
        // ...
    }

    private long getExpireTime() {
        // 在30分钟到1小时之间随机一个时间作为缓存的失效时间
        return 1800 + RANDOM.nextInt(1800);
    }

}

 

什么是Redis缓存穿透?

缓存穿透

        是指恶意的请求,会故意查询数据库不存在的数据,而这些数据在Redis缓存中也不存在,这样就会导致大量的请求都会落到数据库上,造成数据库的压力瞬间增大,从而导致服务器宕机。

解决缓存穿透的方法有很多,其中一种比较常见的方法是采用“缓存空对象”和“BloomFilter(布隆过滤器)两种手段来解决。

缓存空对象

        是指在查询数据库时,如果发现查询的数据不存在,那么就将这个空对象也缓存起来,这样一来,下次再查询这个不存在的数据时,就可以直接在缓存中获取到空对象,而不需要去数据库中查询。

BloomFilter(布隆过滤器)

        【Redis】布隆过滤器_布隆过滤器需要保存-CSDN博客

        是一种概率性数据结构,可以用于判断一个元素是否存在于一个集合中,它的优势在于空间复杂度低、查询速度快。

下面是一个采用了缓存空对象和BloomFilter的Java代码:

public class UserService {

    private RedisTemplate<String, User> redisTemplate;

    private BloomFilter<String> bloomFilter;

    public UserService(RedisTemplate<String, User> redisTemplate, BloomFilter<String> bloomFilter) {
        this.redisTemplate = redisTemplate;
        this.bloomFilter = bloomFilter;
        // 将所有用户的ID都放入BloomFilter中
        List<User> users = getUsersFromDB();
        for (User user : users) {
            bloomFilter.add(user.getId());
        }
    }

    public User getUser(String userId) {
        // 先判断BloomFilter中是否存在该ID
        if (!bloomFilter.mightContain(userId)) {
            return null;
        }
        // 再从缓存中获取数据
        User user = redisTemplate.opsForValue().get(userId);
        if (user != null) {
            return user;
        }
        // 缓存中没有数据,则从数据库中查询
        user = getUserFromDB(userId);
        if (user != null) {
            // 将数据放入缓存
            redisTemplate.opsForValue().set(userId, user, 3600);
        } else {
            // 将空对象放入缓存
            redisTemplate.opsForValue().set(userId, null, 300);
        }
        return user;
    }

    private List<User> getUsersFromDB() {
        // 从数据库中查询所有用户数据
        // ...
    }

    private User getUserFromDB(String userId) {
        // 从数据库中查询用户数据
        // ...
    }

}
``

 

什么是Redis缓存击穿?

缓存击穿

        是指某个热点数据在缓存中失效了,而且这个数据也是经常被访问的数据,这样就会导致大量的请求都会落到数据库上,造成数据库的压力瞬间增大,从而导致服务器宕机。

解决缓存击穿的方法有很多,其中一种比较常见的方法是采用“互斥锁”和“逻辑过期时间”两种手段来解决。

互斥锁

        是指在查询数据库时,如果发现缓存中的数据已经失效,那么就先获取一个互斥锁,然后再去查询数据库,这样一来,只有一个线程去访问数据库,将查询到的数据同步到缓存当中,其他线程就直接从缓存中获取了,就可以避免大量的请求都会落到数据库上。

逻辑过期时间

        是指在查询数据库时,如果发现缓存中的数据已经失效,那么就先将数据库中的数据缓存起来,但是不将这个数据的过期时间设置为实际的过期时间,而是将过期时间设置为一个较短的时间,这样一来,就可以避免缓存中的数据一直都是“冷”数据。

下面是一个采用了互斥锁和逻辑过期时间的Java代码:

public class UserService {

    private RedisTemplate<String, User> redisTemplate;

    private RedissonClient redissonClient;

    public UserService(RedisTemplate<String, User> redisTemplate, RedissonClient redissonClient) {
        this.redisTemplate = redisTemplate;
        this.redissonClient = redissonClient;
    }

    public User getUser(String userId) {
        // 先从缓存中获取数据
        User user = redisTemplate.opsForValue().get(userId);
        if (user != null && !user.isExpired()) {
            return user;
        }
        // 获取互斥锁
        RLock lock = redissonClient.getLock("user:" + userId);
        try {
            if (lock.tryLock(10, 5, TimeUnit.SECONDS)) {
                // 再次从缓存中获取数据
                user = redisTemplate.opsForValue().get(userId);
                if (user != null && !user.isExpired()) {
                    return user;
                }
                // 从数据库中查询数据
                user = getUserFromDB(userId);
                if (user != null) {
                    // 将数据放入缓存,并且设置一个逻辑过期时间
                    redisTemplate.opsForValue().set(userId, user, 3600);
                    user.setExpireTime(System.currentTimeMillis() + 300000);
                }
            }
        } finally {
            // 释放互斥锁
            if (lock != null && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return user;
    }

    private User getUserFromDB(String userId) {
        // 从数据库中查询用户数据
        // ...
    }

}

public class User {

    private String id;

    private String name;

    private long expireTime;

    public User(String id, String name) {
        this.id = id;
        this.name = name;
        this.expireTime = System.currentTimeMillis() + 300000;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public boolean isExpired() {
        return System.currentTimeMillis() > expireTime;
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Segment Anything CSharp| 在 C# 中通过 OpenVINO™ 部署 SAM 模型实现万物分割

​ OpenVINO™ C# API 是一个 OpenVINO™ 的 .Net wrapper&#xff0c;应用最新的 OpenVINO™ 库开发&#xff0c;通过 OpenVINO™ C API 实现 .Net 对 OpenVINO™ Runtime 调用.Segment Anything Model&#xff08;SAM&#xff09;是一个基于Transformer的深度学习模型&#x…

poi4.1导出excel支持xlx,xlsx格式,解决导出execl提示‘文件已经被损坏,无法打开‘

目录 一.maven jar包引入 二.xls格式 三.xlsx格式 一.maven jar包引入 注意&#xff0c;如果要用到xlsx格式&#xff0c;需要导入poi-ooxml <!-- https://mvnrepository.com/artifact/org.apache.poi/poi fx--><!-- 使用xls格式时,只要导入poi-version-yyyymmdd.ja…

Llama模型家族之Stanford NLP ReFT源代码探索 (四)Pyvene论文学习

LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;一&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;二&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;三&#xff09; 基于 LlaMA…

通过双模式对抗提示越狱视觉语言模型

最近&#xff0c;将视觉整合到大型语言模型&#xff08;LLMs&#xff09;中的兴趣显著增加&#xff0c;催生了大型视觉语言模型&#xff08;LVLMs&#xff09;。这些模型结合了视觉和文本信息&#xff0c;如LLaVA和Gemini&#xff0c;已经在包括图像字幕、视觉问题回答和图像检…

「动态规划」打家劫舍的变形题,你会做吗?

213. 打家劫舍 IIhttps://leetcode.cn/problems/house-robber-ii/description/ 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈&#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#x…

下载安装Thonny并烧录MicroPython固件至ESP32

Thonny介绍 一、Thonny的基本特点 面向初学者&#xff1a;Thonny的设计初衷是为了帮助Python初学者更轻松、更快速地入门编程。它提供了直观易懂的用户界面和丰富的功能&#xff0c;降低了编程的门槛。轻量级&#xff1a;作为一款轻量级的IDE&#xff0c;Thonny不会占用过多的…

中国各省份简称的命名根据是什么?省份简称顺口溜

我国共有34个省级行政区域,包括23个省,5个自治区,4个直辖市,2个特别行政区。每个省份都有自己对应的简称,而省份简称的由来,可以分为以下三种: 一、取省份全称中的一部分作为简称 比如,北京的简称是“京”,天津的简称是“津”,东北三兄弟的简称是“黑吉辽”,这种简单…

数据库之PostgreSQL详解

一、PostgreSQL介绍 PostgreSQL是一个功能强大的 开源 的关系型数据库。底层基于C实现。 PostgreSQL的开源协议和Linux内核版本的开源协议是一样的。。BDS协议&#xff0c;这个协议基本和MIT开源协议一样&#xff0c;说人话&#xff0c;就是你可以对PostgreSQL进行一些封装&a…

OpenFeign远程接口调用使用公共模块出现的错误

今天在使用openfeign和sentinel实现fallback服务降级时遇到找不到类型的异常 检查代码发现没有错误&#xff0c;EnableFeignClients也在启动类上标注了 错误信息&#xff1a;A component required a bean of type com.zxc.cloud.apis.PayFeignSentinelApi that could not be f…

类和对象(下+)_const成员、初始化列表、友元、匿名对象

类和对象&#xff08;下&#xff09; 文章目录 类和对象&#xff08;下&#xff09;前言一、const成员二、友元1.友元函数2.友元类 三、初始化列表四、explicit关键字五、匿名对象总结 前言 static成员、内部类、const成员、初始化列表、友元、匿名对象 一、const成员 将cons…

[Cloud Networking] Layer 2

文章目录 1. 什么是Mac Address?2. 如何查找MAC地址&#xff1f;3. 二层数据交换4. [Layer 2 Protocol](https://blog.csdn.net/settingsun1225/article/details/139552315) 1. 什么是Mac Address? MAC 地址是计算机的唯一48位硬件编码&#xff0c;嵌入到网卡中。 MAC地址也…

100道面试必会算法-32-二叉树右视图用栈实现队列

100道面试必会算法-32-二叉树右视图&用栈实现队列 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4]示例 2: 输入: [1,n…

基于vue的音乐播放器的设计与实现(论文+源码)_kaic

摘 要 当下&#xff0c;如果还依然使用纸质文档来记录并且管理相关信息&#xff0c;可能会出现很多问题&#xff0c;比如原始文件的丢失&#xff0c;因为采用纸质文档&#xff0c;很容易受潮或者怕火&#xff0c;不容易备份&#xff0c;需要花费大量的人员和资金来管理用纸质文…

java版spring cloud 深入探究ERP管理系统源码:功能模块详解与操作流程梳理

随着数字化转型的深入&#xff0c;企业对于高效、稳定且具有扩展性的管理系统的需求日益增加。为此&#xff0c;我们开发了一套基于Java技术的鸿鹄ERP管理系统&#xff0c;该系统整合了Spring Cloud Alibaba、Spring Boot、MybatisPlus、Redis等前沿技术&#xff0c;并采用了VU…

Tensorflow入门实战 P03-天气识别

目录 1、完整代码 2、运行结果 2.1 查看20张图片 2.2 程序运行 2.3 运行结果 3、小结 ① 代码运行过程中有报错&#xff1a; ② 修改代码如下&#xff1a; ③ 分析原因&#xff1a; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&…

【MySQL】服务器配置和管理

本文使用的MySQL版本是8.0 MySQL服务器介绍 MySQL服务器通常说的是mysqld程序。 mysqld 是 MySQL 数据库服务器的核心程序&#xff0c;负责处理客户端的请求、管理数据库和执行数据库操作。管理员可以通过配置文件和各种工具来管理和监控 mysqld 服务器的运行 官方文档&…

OrangePi AIpro小试牛刀-目标检测(YoloV5s)

非常高兴参加本次香橙派AI Pro&#xff0c;香橙派联合华为昇腾打造的一款AI推理开发板评测活动&#xff0c;以前使用树莓派Raspberry Pi4B 8G版本&#xff0c;这次有幸使用国产嵌入式开发板。 一窥芳容 这款开发板搭载的芯片是和华为昇腾的Atlas 200I DK A2同款的处理器&#…

Vue3【十四】watchEffect自动监视多个数据实现,不用明确指出监视哪个数据

Vue3【十四】watchEffect自动监视多个数据实现&#xff0c;不用明确指出监视哪个数据 Vue3【十四】watchEffect自动监视多个数据实现&#xff0c;不用明确指出监视哪个数据 进入立即执行一次&#xff0c;并监视数据变化 案例截图 目录结构 代码 Person.vue <template>&…

element-plus的el-text组件(文本组件)的介绍和使用

el-text&#xff08;适合文本操作的组件&#xff09; 设置文本type,如default,primary,success,info,warning,danger超出容器尺寸自动省略&#xff0c;tuncated属性设置size属性控制文本大小&#xff0c;有large,default,small设置tag属性&#xff0c;值为html5标签名&#xf…

统信UOS1070上配置文件管理器默认属性02

原文链接&#xff1a;统信UOS 1070上配置文件管理器默认属性01 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在统信UOS 1070上配置文件管理器默认属性的第二篇文章——配置工作区视图。文件管理器中的工作区视图配置可以帮助我们更好地组织和管理文件&#xff0c;…