一、什么是缓存穿透、缓存击穿、缓存雪崩

1、为啥使用缓存?

  1. 在程序内部使用缓存,将经常使用的数据存储在缓存中,可以减少对数据库的频繁访问,从而提高系统的响应速度和性能。缓存可以将数据保存在内存中,读取速度更快,能够大大缩短数据访问的时间,提升用户体验。
  2. 缓存不仅可以提高系统的性能和吞吐量,还可以提高系统的可靠性和稳定性。还可以减少网络传输的负载,特别是在分布式系统中。能够节省网络带宽和服务器的资源消耗。
  3. 使用缓存可以优化系统的性能、提高响应速度、降低数据库负载、节省网络传输和服务器资源,从而提升用户体验和系统的可靠性
  4. 其实就是以空间换时间

2、名词解析

词语解析说明redis中是否存在数据库中是否存在
缓存穿透查询一个不存在的数据,缓存中没有数据直接穿透缓存,查询数据库,造成数据库的压力。不存在不存在
缓存击穿缓存中的某个热点数据过期,大量的并发请求访问这个数据。导致请求在瞬间直接请求数据库,数据库压力过大甚至崩溃。不存在存在
缓存雪崩指在同一时段大量的缓存失效,导致数据查询直接打到数据库,可能会使数据库崩溃不存在存在

3、原因分析

词语解析可能的原因
缓存穿透被攻击。小可爱通过构造恶意请求,使得缓存层无法命中任何数据
缓存击穿缓存中的热点数据设置了过期时间,数据失效了
缓存雪崩大量的数据在同一时间失效

4、缓存穿透

4.1、缓存穿透示意图

在这里插入图片描述
如上图,小可爱发送一个亿的请求,因为数据本身不存在,如果逻辑没有处理好。一亿的请求都会命中数据库。那该怎么解决嘞?

4.2、解决方案

4.2.1、缓存空对象

判断数据库查询结果

1、存在,将数据缓存起来[key,结果]

2、不存在,将空对象一般是null或者空数组[]缓存起来[key,null]或[key,[]]

下面的代码,如果ID在数据库中不存在,则直接查询数据库,返回的是空数组,后续再查询的话,redis认为有数据,有效解决缓存穿透

public DictBO queryDictById(Long id) {
    DictBO dictBO = redisUtil.get(String.valueOf(id));
    if(!ObjectUtils.isEmpty(dictBO)){
        return dictBO;
    }else{
        dictBO = this.getById(id);
        redisUtil.setEx(String.valueOf(dictBO.getId()), dictBO, Duration.ofHours(1L));
        return dictBO;
    }
}
4.2.1.1、优点

实现简单

4.2.1.2、缺点

内存消耗(一亿的数据量还是挺大的),因此要设置过期时间TTL

4.2.2、布隆过滤器
4.2.2.1、布隆过滤器示例代码
package com.toto.redis.filter;

import java.util.BitSet;

/**
 * @Description: MyBloomFilter
 * @Package: com.toto.redis.filter
 * @Author gufanbiao
 * @CreateTime 2024-06-21 21:06
 */
public class MyBloomFilter {
    /** 一个长度为10 亿的比特位 */
    private static final int DEFAULT_SIZE = 256 << 22;
    /** 为了降低错误率,使用加法hash算法,所以定义一个8个元素的质数数组 */
    private static final int[] seeds = {3, 5, 7, 11, 13, 31, 37, 61};
    /** 相当于构建 8 个不同的hash算法 */
    private static HashFunction[] functions = new HashFunction[seeds.length];
    /** 初始化布隆过滤器的 bitmap */
    private static BitSet bitset = new BitSet(DEFAULT_SIZE);

    /**
     * 添加数据
     * @param value 需要加入的值
     */
    public static void add(String value) {
        if (value != null) {
            for (HashFunction f : functions) {
                //计算 hash 值并修改 bitmap 中相应位置为 true
                bitset.set(f.hash(value), true);
            }
        }
    }

    /**
     * 判断相应元素是否存在
     * @param value 需要判断的元素
     * @return 结果
     */
    public static boolean contains(String value) {
        if (value == null) {
            return false;
        }
        boolean ret = true;
        for (HashFunction f : functions) {
            ret = bitset.get(f.hash(value));
            //一个 hash 函数返回 false 则跳出循环
            if (!ret) {
                break;
            }
        }
        return ret;
    }

    public static void main(String[] args) {
        for (int i = 0; i < seeds.length; i++) {
            functions[i] = new HashFunction(DEFAULT_SIZE, seeds[i]);
        }
        // 添加1亿数据
        for (int i = 0; i < 100000000; i++) {
            add(String.valueOf(i));
        }
        String id = "123456789";
        add(id);
        System.out.println(contains(id));   // true
        System.out.println("" + contains("234567890"));  //false
    }
}

class HashFunction {
    private int size;
    private int seed;
    public HashFunction(int size, int seed) {
        this.size = size;
        this.seed = seed;
    }
    public int hash(String value) {
        int result = 0;
        int len = value.length();
        for (int i = 0; i < len; i++) {
            result = seed * result + value.charAt(i);
        }
        int r = (size - 1) & result;
        return (size - 1) & result;
    }
}
4.2.2.2、布隆过滤器示例代码使用

相当于是在redis前加了一层过滤
在这里插入图片描述

public DictBO queryDictById(Long id) {
	// 使用布隆过滤器
    boolean contains = MyBloomFilter.contains(String.valueOf(id));
    if(!contains){
        return null;
    }
    DictBO dictBO = redisUtil.get(String.valueOf(id));
    if(!ObjectUtils.isEmpty(dictBO)){
        return dictBO;
    }else{
        dictBO = this.getById(id);
        redisUtil.setEx(String.valueOf(dictBO.getId()), dictBO, Duration.ofHours(1L));
        return dictBO;
    }
}
4.2.2.3、优点

1、使用布隆过滤器技术来过滤掉无效的请求,将可能不存在的数据快速过滤掉,

2、内存占用少

4.2.2.4、缺点

1、需要提前将数据库数据预热到布隆过滤器中

2、由于数据结构和算法导致无法删除热键,只能新增;

4.2.2.5、其它增强

增强 id 的复杂度、加强用户权限校验,做好热点参数的限流

5、缓存击穿

缓存击穿是某一个热点key同时失效,恰巧这一瞬间无数的请求同时到服务器,多个线程查询redis且redis无数据,这时这些请求会同时去查询数据库,影响数据库的性能。

5.1、缓存击穿示意图

在这里插入图片描述

5.2、解决方案

5.2.1、热点数据设置"永不过期"

这种解决方式,设置TTL的时间为-1,或者设置了时间,在过期前主动更新时间,其实热点数据可能也会发生变化,将变化的数据在非高并发时间段更新缓存也可以。

网上也有“逻辑过期”,其实是将过期时间放在了key对应的value中,在代码中加逻辑判断就可以。

5.2.2、加锁(分布式锁)或者使用队列控制

在这里插入图片描述

在紫色区域,用户1和用户2同时访问程序,在java中会开启两个线程执行程序,假设线程1先执行判断逻辑,不存在就对key进行加锁处理,线程2执行时获取锁失败后,使用线程等待,进行重试即可。

这里不再贴出代码,后面章节会对锁进行详细的说明,或者百度。

5.2.2.1、优点

保证一致性

5.2.2.2、缺点

1、线程需要等待,影响性能

2、程序处理逻辑若有漏洞,会造成死锁

5.2.3、限流和熔断

必要时实现服务限流和熔断机制,防止因为某个服务不可用而影响整个系统。现在在使用互联网应用时,熔断和限流的体验是有,但不多。不到万不得已,不太建议使用。

6、缓存雪崩

缓存雪崩和缓存击穿在概念上的区别在于:缓存击穿是部分key过期导致的严重后果,而缓存雪崩则是因为大量key同时过期所导致的问题。你给了我一击,为什么还要一次又一次的暴击。

当然造成雪崩的现象还有另外一种原因:redis服务挂了。

6.1、如何防止缓存雪崩?

1、设置合理的缓存失效时间,避免大量缓存同时失效。

2、实现缓存数据的分布式锁,确保同时只有一个客户端去数据库中查询数据,其他客户端等待。

3、利用Redis集群或者一致性哈希,分散key的分布,避免热点数据集中失效。

4、如果缓存数据设置了过期时间,可以在失效前主动更新缓存数据。

期**所导致的问题。你给了我一击,为什么还要一次又一次的暴击。

当然造成雪崩的现象还有另外一种原因:redis服务挂了。

6.1、如何防止缓存雪崩?

1、设置合理的缓存失效时间,避免大量缓存同时失效。

2、实现缓存数据的分布式锁,确保同时只有一个客户端去数据库中查询数据,其他客户端等待。

3、利用Redis集群或者一致性哈希,分散key的分布,避免热点数据集中失效。

4、如果缓存数据设置了过期时间,可以在失效前主动更新缓存数据。

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

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

相关文章

uniapp——上传图片获取到file对象而非临时地址——基础积累

最近在看uniapp的代码&#xff0c;遇到一个需求&#xff0c;就是要实现上传图片的功能 uniapp 官网地址&#xff1a;https://uniapp.dcloud.net.cn/ 上传图片有对应的API&#xff1a; uni.chooseImage方法&#xff1a;https://uniapp.dcloud.net.cn/api/media/image.html#choo…

【Python机器学习】分类向量——数字可以编码分类变量

在adult数据集的例子中&#xff0c;分类变量被编码为字符。一方面可能会有拼写错误&#xff0c;但另一方面&#xff0c;它明确的将一个变量标记为分类变量。无论是为了便于存储还是因为数据的手机方式&#xff0c;分类变量通常被编码为整数。 假设adult数据集中的人口普查数据…

windows系统根据端口查询pid并结束进程 netstat taskkill

用管理员权限打开命令指示符,输入命令&#xff1a; 1、查看被占用端口所对应的 PID netstat -aon|findstr “端口号” 2、查看指定PID的进程 tasklist|findstr ”14816” 3、结束进程 taskkill -pid 进程号 -f

秋招突击——6/24——复习{完全背包问题——买书,状态转换机——股票买卖V}——新作{两数相除,LRU缓存实现}

文章目录 引言复习完全背包问题——买书个人实现 状态转换机——股票买卖V个人实现参考实现 新作两数相除个人实现 新作LRU缓存实现个人实现unordered_map相关priority_queue相关 参考实现自己复现 总结 引言 今天知道拼多多挂掉了&#xff0c;难受&#xff0c;那实习就是颗粒无…

4_FOC之Clarke变换原理及推导_1

三相PMSM的数学模型是一个比较复杂且强耦合的多变量系统。为了便于后期控制器设计&#xff0c;必须选择合适的坐标变换对数学模型进行降阶和解耦变换。 1、什么是Clark变换 静止abc轴系与αβ轴系如上图。为满足功率不变约束&#xff0c;在图中设αβ轴系中定子绕组以及转子绕组…

# [0622] Task02 model-free 免模型类 RL 算法的预测和控制 【ε 贪心策略 优化的证明】

easy-rl PDF版本 笔记整理 P3 joyrl 比对 补充 P4 - P5 相关 代码 整理 ——> 有空 另开一页 最新版PDF下载 地址&#xff1a;https://github.com/datawhalechina/easy-rl/releases 国内地址(推荐国内读者使用)&#xff1a; 链接: https://pan.baidu.com/s/1isqQnpVRWbb3yh8…

学好 prompt 让大模型变身撩富婆专家,带你走上人生巅峰

前文 使用大模型的最重要的一步就是编写好的提示词 prompt &#xff0c;但是 prompt 既容易被低估也容易被高估。被低估是因为设计良好的提示词可以显著提升效果。被高估是因为即使是基于提示的应用也需要大量的工程工作才能使其发挥作用。下面我会介绍在编写 prompt 的时候&a…

无芯封装基板适用于先进封装技术 我国行业发展面临一定挑战

无芯封装基板适用于先进封装技术 我国行业发展面临一定挑战 无芯封装基板指去除作为核心支撑层的芯板&#xff0c;仅由积层板构成的封装基板。与传统带有芯层的封装基板相比&#xff0c;无芯封装基板具有轻量化、密度高、信号传输质量高、散热性能好、布线灵活性好等优势&#…

靶机渗透之DC-7

一、信息收集 扫描网段&#xff0c;发现靶机ip为192.168.145.235。 nmap -sP 192.168.145.* 进一步对端口&#xff0c;靶机系统等信息进行一个收集。可以看到开放了22端口&#xff0c;80端口&#xff0c;主机系统为linux等信息。 nmap -sT -T4 -O -sV -sC -p1-65535 192.16…

品牌电商维权:应对渠道低价与假货的有力举措

在品牌治理渠道的过程中&#xff0c;会遭遇各种各样的问题&#xff0c;其中低价现象尤为突出。低价往往导致经销商被迫跟价&#xff0c;而未授权的店铺则更加不受管控&#xff0c;更容易出现低价情况。然而&#xff0c;低价本身不能直接作为品牌管控渠道的充分理由&#xff0c;…

元数据管理的发展历程你了解吗?元数据管理要克服哪些挑战?

在当今的信息化时代&#xff0c;数据的价值已被广泛认可&#xff0c;而元数据作为描述数据的数据&#xff0c;其作用日益凸显。元数据管理&#xff0c;作为确保数据质量、促进数据共享和提高数据透明度的关键环节&#xff0c;对企业的数据战略至关重要。随着技术的发展&#xf…

理解MySQL索引:提升查询性能的关键

一、前言 在众多数据库中&#xff0c;MySQL以其高效、稳定和跨平台的特点成为许多开发者的首选。然而&#xff0c;随着数据量的不断增加&#xff0c;查询性能可能会成为一个瓶颈。这时&#xff0c;索引&#xff08;Index&#xff09;便成为了提升查询速度的关键工具。本篇文章…

if action和Switch之间该怎么选择?

1. Switch 2. If及If Action Subsystem 3.结论 元素很多&#xff0c;用switch 元素少&#xff0c;用if或switch 如果...很多&#xff0c;用if

Linux服务升级:Almalinux 升级 WebCatlog桌面程序

目录 一、实验 1.环境 2.Almalinux 升级 WebCatlog桌面程序 二、问题 1.Ubuntu如何升级 WebCatlog桌面程序 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统版本软件IP备注Almalinux9.4 WebCatlog 192.168.204.150 &#xff08;2&#xff09;Termi…

Redis数据结构跳跃表skiplist

一、介绍 Redis中使用跳跃表&#xff08;skiplist&#xff09;来实现有序集合&#xff08;sorted set&#xff09;和有序字典&#xff08;sorted dictionary&#xff09;数据结构。 跳跃表是一种有序的数据结构&#xff0c;它由多层链表组成。每一层链表都是一个有序的链表&a…

零成本搭建个人图床服务器

前言 图床服务器是一种用于存储和管理图片的服务器&#xff0c;可以给我们提供将图片上传后能外部访问浏览的服务。这样我们在写文章时插入的说明图片&#xff0c;就可以集中放到图床里&#xff0c;既方便多平台文章发布&#xff0c;又能统一管理和备份。 当然下面通过在 Git…

祝贺:东兴朱雀桥成为一点点的NFC果汁供应商。

东兴朱雀桥进出口&#xff1a;品质之选&#xff0c;护航一点点奶茶的成长&#xff01; 据记者了解&#xff0c;该家公司是专注于进口越南特色NFC果汁&#xff1a;薇妮她VINUT人参果汁饮料的研发与生产&#xff0c;以其丰富的产品线和卓越品质&#xff0c;成为了行业内的佼佼者…

华为云鲲鹏架构docker部署2048小游戏

华为云鲲鹏架构docker部署2048小游戏 1. 鲲鹏架构ESC2. 配置docker3. 上传2048镜像4. 删除容器,镜像 1. 鲲鹏架构ESC 2. 配置docker 安装dockeryum -y install docker开机启动 systemctl enable docker启动docker服务 systemctl start docker查询docker的运行版本 docker -v3…

零知识学习之DPDK与RDMA(1)—— 认识DPDK(1)

接前一篇文章&#xff1a;零知识学习之DPDK与RDMA&#xff08;1&#xff09;—— 序言与初识 本文内容参考&#xff1a; 《Linux高性能网络详解 从DPDK、RDMA到XDP》 刘伟著 人民邮电出版社 DPDK首页、文档和下载 - 网络数据包转发处理 - OSCHINA - 中文开源技术交流社区 五…

从理论到实践:工业工厂室外可燃气体报警器的校准方法

随着工业工厂对安全生产要求的不断提高&#xff0c;可燃气体报警器作为防范火灾、爆炸事故的重要设备&#xff0c;其准确性和可靠性显得尤为重要。 特别是在室外环境中&#xff0c;由于气候条件多变、设备老化等因素的影响&#xff0c;可燃气体报警器的性能可能会发生变化。因…