缓存穿透、缓存雪崩和缓存击穿

1 缓存穿透

缓存穿透是指查询一个一定不存在的数据,由于缓存中没有,每次查询都要去数据库中查询,导致频繁地访问数据库,从而影响系统的性能。攻击者可以利用这一点,对系统进行拒绝服务攻击。

在这里插入图片描述

1.1 缓存穿透举例

  1. 攻击者通过在请求中携带不存在的数据,进行大量的请求,导致系统访问数据库频繁,从而影响系统性能。

  2. 用户在查询不存在的数据时,由于缓存中没有,每次都会去数据库中查询,也会造成缓存穿透。

1.2 解决方法

  1. 使用布隆过滤器对查询的键进行过滤,如果查询的键不存在于布隆过滤器中,则直接返回不存在,不再查询缓存和数据库。
    布隆过滤器是一种空间效率很高的随机数据结构,它利用位数组和哈希函数实现,可以用于检索一个元素是否在一个集合中。布隆过滤器有一定的误判率,但是可以通过调整位数组的大小和哈希函数的数量来控制误判率。

  2. 如果查询的数据在数据库中不存在,则将空对象放入缓存中,下次再查询时直接从缓存中获取空对象,避免了频繁地去查询数据库。
    例如,当用户查询某个不存在的商品时,将一个空的商品对象放入缓存中,下次再查询时直接从缓存中获取该空对象。这样即使用户频繁地查询不存在的商品,也不会对数据库造成压力。

  3. 在应用启动时,或者定期地将热点数据加载到缓存中,避免缓存中没有数据导致的缓存穿透。
    热点数据是指访问频率高、对系统性能影响大的数据。将热点数据预先加载到缓存中可以避免缓存穿透。可以在应用启动时,或者定期地将热点数据加载到缓存中。可以使用缓存预热技术实现。

  4. 对请求增加校验机制,过滤掉不合理请求
    例如:课程Id是长整型,如果发来的不是长整型则直接返回。

1.3 名词解释

1.3.1 布隆过滤器

布隆过滤器是一种数据结构,可以高效地判断一个元素是否存在于一个集合中。它的主要优点是占用内存空间小、判断速度快,适用于需要快速判断元素是否存在于集合中的场景。布隆过滤器基于哈希函数实现,将元素映射到一个位数组中,并使用多个哈希函数进行映射,从而降低误判率。但是,由于布隆过滤器的空间有限,当元素数量过多时,误判率会增加,从而导致布隆过滤器失效。

1.3.1.1 布隆过滤器的优点
  1. 占用内存小:布隆过滤器只需要一段位数组和多个哈希函数,占用内存空间很小。

  2. 判断速度快:布隆过滤器只需要进行位运算,判断速度非常快。

  3. 可以判断元素是否一定不存在于集合中:如果布隆过滤器判断某个元素不存在于集合中,那么该元素一定不存在于集合中。

1.3.1.2 布隆过滤器的缺点
  1. 误判率高:由于布隆过滤器使用多个哈希函数进行映射,误判率会随着哈希函数数量的增加而降低,但仍然存在误判率。

  2. 无法删除元素:由于布隆过滤器的位数组是基于哈希函数映射得到的,无法删除某个元素。

  3. 受限于容量:当元素数量过多时,误判率会增加,从而导致布隆过滤器失效。

1.3.1.3 布隆过滤器容易失效的场景
  1. 元素数量过多:当布隆过滤器中的元素数量过多时,误判率会增加,从而导致布隆过滤器失效。

  2. 哈希函数数量不足:布隆过滤器的误判率与哈希函数数量有关,当哈希函数数量不足时,误判率会增加,从而导致布隆过滤器失效。

  3. 元素分布不均匀:当元素在哈希函数映射后分布不均匀时,误判率会增加,从而导致布隆过滤器失效。

总的来说,布隆过滤器适用于需要快速判断元素是否存在于集合中的场景,但需要注意它的误判率和容量限制,以及容易失效的场景。在使用布隆过滤器时,需要根据具体场景进行调整,以达到合理的使用效果。

2 缓存雪崩

缓存雪崩是指缓存中大量的数据同时失效,导致大量的请求直接打到数据库上,从而使得数据库承受不了巨大的压力,最终导致整个系统崩溃的现象。缓存雪崩通常是由于缓存中的键同时过期或者缓存服务宕机等原因引起的。

2.1 缓存雪崩举例

  1. 在某个时间点,所有的缓存数据都过期了。由于缓存中不存在有效的数据,所有的请求都会直接打到数据库上,导致数据库承受巨大的压力,最终导致整个系统崩溃。

  2. 某个缓存服务宕机了,所有的请求都无法得到缓存服务的响应,直接打到数据库上,导致数据库承受巨大的压力,最终导致整个系统崩溃。

2.2 解决方法

  1. 缓存数据的过期时间设置随机,避免缓存数据同时失效。可以将缓存数据的过期时间加上一个随机值,避免缓存数据同时失效。比如,将缓存数据的过期时间加上一个随机值,可以使得缓存数据的失效时间分散在时间轴上,避免缓存数据同时失效。
redisTemplate.opsForValue().set("key", JSON.toJSONString(valueObject),30 + new Random().nextInt(100), 
TimeUnit.SECONDS);
  1. 使用分布式缓存,避免单点故障。使用分布式缓存可以避免单点故障,提高缓存服务的可用性。可以使用Redis Cluster、Memcached等分布式缓存来替代单机缓存。

  2. 数据预热,避免缓存冷启动。在系统启动或者低峰期时,将一些热点数据预先加载到缓存中,避免缓存冷启动。可以使用缓存预热技术实现。

  3. 多级缓存,避免缓存失效时的“一次性打击”。多级缓存可以避免缓存失效时的“一次性打击”,提高缓存服务的稳定性。可以使用本地缓存和分布式缓存相结合的方式来实现多级缓存。

  4. 数据库压力保护。可以通过限流、降级等手段来保护数据库,避免数据库承受巨大的压力。可以使用限流、降级等技术来控制数据库的访问量。

3 缓存击穿

缓存击穿是指缓存中不存在的数据被大量请求,导致请求直接打到数据库上,从而使得数据库承受巨大的压力,最终导致整个系统崩溃的现象。缓存击穿通常是由于热点数据集中、缓存过期时间设置不合理等原因引起的。

在这里插入图片描述

3.1 缓存击穿举例

  1. 某个商品的详情信息是热点数据,每秒有很多请求访问该商品详情信息。如果缓存中不存在该商品的详情信息,那么所有请求都会直接打到数据库上,导致数据库承受巨大的压力,最终导致整个系统崩溃。

  2. 某个恶意用户故意请求一个不存在于缓存中的key,每秒有很多请求访问该key。如果缓存中不存在该key,那么所有请求都会直接打到数据库上,导致数据库承受巨大的压力,最终导致整个系统崩溃。

3.2 解决方法

  1. 使用互斥锁或者分布式锁,避免缓存击穿。在缓存失效时,使用互斥锁或者分布式锁,避免缓存击穿。在使用锁的时候,需要注意锁的粒度,尽量避免锁的粒度过大,影响系统的并发性能。

  2. 设置热点数据永不过期。对于热点数据,可以设置其永不过期,避免缓存失效。当然,这种方式需要注意缓存数据的大小,不要将所有数据都设置成永不过期,影响系统的内存使用。

  3. 在缓存失效时,设置短暂的锁定时间。在缓存失效时,可以设置短暂的锁定时间,避免缓存击穿。在锁定时间内,所有请求都会等待锁被释放后再访问数据库,避免了缓存击穿。

  4. 使用异步加载,避免缓存击穿。可以使用异步加载技术,将缓存数据的加载异步化,降低缓存击穿的风险。在缓存失效时,可以异步地加载数据到缓存中,避免大量请求直接打到数据库上。

  5. 增加缓存层,避免缓存击穿。可以增加缓存层,将热点数据缓存到更高层次的缓存中,避免缓存击穿。比如,可以将热点数据缓存到CDN中,避免请求直接打到数据库上。

3.3 名词解释

3.3.1 异步加载

异步加载是指在应用程序中,将数据加载操作放在后台线程中执行的一种技术。它的作用是提高系统的响应速度,并避免缓存失效时大量请求直接打到数据库上,导致数据库负载过高的情况,从而保证系统的稳定性。

在使用异步加载时,应用程序会在缓存失效时向后台线程发送请求,请求后台线程异步地从数据库中加载数据,并将数据存储到缓存中。后台线程会根据任务队列中的请求,异步地从数据库中加载数据,并在加载完成后将加载结果返回给主线程,主线程可以使用加载好的数据进行相应的操作。通过这种方式,应用程序可以避免主线程的阻塞,提高系统的响应速度。同时,异步加载还可以避免缓存击穿的风险,使系统更加稳定可靠。

3.3.1.1 异步加载举例

举个例子,假设我们有一个电商应用,需要加载商品列表数据。为了提高系统的响应速度,我们可以使用异步加载技术,将商品列表数据的加载异步化。

具体操作步骤如下:

  1. 当用户进入商品列表页面时,应用程序会向后台线程发送请求,请求后台线程加载商品列表数据。

  2. 后台线程会将请求放入任务队列中,等待执行。

  3. 后台线程会根据任务队列中的请求,异步地从数据库中加载商品列表数据,并将数据存储到缓存中。

  4. 当商品列表数据加载完成后,后台线程会将加载结果返回给主线程,主线程可以使用加载好的商品列表数据进行相应的操作,例如展示在页面上。

通过异步加载技术,我们可以避免用户在等待商品列表数据加载时出现卡顿的情况,提高了系统的响应速度。同时,如果缓存失效时,异步加载还可以避免大量请求直接打到数据库上,导致数据库负载过高的情况,从而保证了系统的稳定性。

异步加载是在缓存命中失败时才会触发的。 当缓存命中成功时,应用程序可以直接返回缓存中的数据,避免了不必要的数据库查询操作,从而提高了系统的性能。只有当缓存命中失败时,应用程序才会向后台线程发送请求,请求后台线程异步地从数据库中加载数据,并将数据存储到缓存中,这样可以避免缓存击穿的风险。因此,在实际应用中,异步加载通常是在缓存命中失败时才会使用的。

3.3.2 增加缓存层

增加缓存层是一种常见的避免缓存击穿的方法,可以将热点数据缓存到更高层次的缓存中,避免请求直接打到数据库上,从而提高系统的性能和稳定性。

下面是具体的解释:

  1. 缓存层级划分
    将缓存划分为多个层级,按照访问频率和数据更新频率的高低,将热点数据放在更高层次的缓存中。例如,可以将热点数据缓存到CDN中,将相对冷门的数据缓存到本地缓存或者分布式缓存中,将最不常用的数据缓存到数据库中。

  2. CDN缓存
    使用CDN缓存来缓存热点数据,可以将数据缓存在离用户更近的地方,避免请求直接打到数据库上。CDN缓存可以根据用户的地理位置,选择离用户更近的节点进行缓存,从而提高访问速度和稳定性。

  3. 缓存更新
    对于经常被访问和更新的数据,需要使用缓存更新策略,避免缓存失效后直接打到数据库上,导致缓存击穿。常见的缓存更新策略有定时更新和异步更新。定时更新是指在缓存过期前,定期将缓存中的数据更新为最新状态;异步更新是指在缓存失效后,异步地从数据库中加载数据,并将数据更新到缓存中。

  4. 缓存预热
    缓存预热是指在系统启动时,将热点数据提前加载到缓存中,避免缓存失效后直接打到数据库上,导致缓存击穿。缓存预热可以通过定时任务或者手动触发来实现。

综上所述,增加缓存层是一种有效的避免缓存击穿的方法,可以提高系统的性能和稳定性。但需要注意的是,缓存层级划分和缓存更新策略需要根据实际情况进行调整,避免缓存命中率过低或者缓存更新过于频繁,影响系统的性能。

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

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

相关文章

Qt Plugin插件开发

一、Qt 插件机制 .1 Qt 插件简介 插件是一种遵循一定规范的应用程序接口编写出来的程序,定位于开发实现应用软件平台不具备的功能的程序。插件与宿主程序之间通过接口联系,就像硬件插卡一样,可以被随时删除,插入和修改&#xff…

docker学习笔记(二)

目录 启动Docker ​编辑 建立 Docker 用户 ​编辑 测试 Docker 是否正常工作 卸载Docker Docker镜像加速器配置 配置镜像 检查加速器是否生效 如何在Linux中的.json文件下保存并退出 如果我是使用vi操作进来的,我该如何保存并退出呢? 如何在Li…

基于粒子群优化算法的最佳方式优化无线传感器节点的位置(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 此代码优化了由于电池耗尽而产生覆盖空洞后 WSN 节点的位置。如果活动通信中的任何节点死亡,则通过PSO优化再次定位…

Java Socket和ServerSocket 使用

在Java中,Socket和ServerSocket是用于创建网络连接的重要类。Socket类用于创建客户端套接字,而ServerSocket类用于创建服务器套接字。在本文中,我们将讨论Socket和ServerSocket的作用、使用方法以及相关代码示例。 Socket的作用 Socket是Jav…

【2023 · CANN训练营第一季】应用开发深入讲解——第四章 DVPP初级

学习资源 1.JPEG图片解码 文档 2.图片缩放 文档 媒体数据处理 数据预处理的典型使用场景 数据预处理的多种方式 分为两种,AIPP和DVPP DVPP数据预处理功能 了解两个重要概念 宽stride 和 高stride 理解:这里假设一张图片的宽为500,高为3…

匹配算法之 匈牙利算法详解

参考: 算法学习笔记(5):匈牙利算法漫谈匈牙利算法匈牙利算法、KM算法匈牙利算法(二分图)通俗易懂小白入门)二分图最大匹配——匈牙利算法多目标跟踪之数据关联(匈牙利匹配算法和KM算法)【小白学…

187页9万字企业大数据治理与云平台实施方案(word)

1 项目背景概述 1.1 项目背景理解 1.2 项目需求范围 2 项目技术方案 2.1 咨询研究服务方案 2.1.1 咨询研究服务内容 2.1.2 咨询服务方案 2.2 第三方独立评估 2.2.1 概述 2.2.2 管理办法 2.2.3 考核机制 2.3 安全咨询研究服务方案 2.3.1 安全咨询服务内…

【k8s】【ELK】日志环境部署【待写】

1、日志收集基本概念 k8s中pod的路径: containers log: /var/log/containers/*.log Pod log: /var/log/pods docker log: /var/lib/docker/containers/*/*.log如何收集日志 使用 EFKLogstashKafka 1、filebeat读取容器中的日志,然后写入K…

ChatGPT在小红书文案实践

今天聊一聊ChatGPT在小红书这个实际应用场景的案例。ChatGPT 以较低的门槛提高了使用者创作水平,有较高的下限,但如何创造更高质量的内容就要依靠使用者在领域的能力和AI使用技巧,作者无任何小红书推广和文案写作经验,文章内容来自…

快速排序、希尔排序、归并排序、堆排序、插入排序、冒泡排序、选择排序(递归、非递归)C语言详解

1.排序的概念及其运用 1.1排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录&a…

python中使用opencv LED屏数字识别(可用做车牌识别,一样的原理)

应项目要求需要基于cpu的LED数字识别,为了满足需求,使用传统方法进行实验。识别传感器中显示的数字。因此使用opencv的函数做一些处理,实现功能需求。 首先读取图像,因为我没想大致得到LED屏幕的区域,因此将RGB转换为H…

postman处理各种请求数据

1、后台request接收postman参数 2、后台单个参数接收postman 3、后台RequestParam参数接收postman 注意事项:情况一:全部都是单个字符串的 情况二:有可能是一个json对象序列化成字符串过来的,那么需要在form-data中设置 …

鸿蒙Hi3861学习十-Huawei LiteOS-M(消息队列)

一、简介 消息队列,是一种常用于任务间通信的数据结构,实现了接收来自任务或中断的不固定长度的消息,并根据不同的接口选择传递消息是否存放在自己空间。任务能够从队列里面读取消息,当队列中的消息是空时,挂起读取任务…

国内免费cdn汇总2023最新

内容分发网络简称CDN,其原理大概是将网站内容分发至加速节点,让用户从就近的服务器节点上获取内容,从而提高网站的访问加载速度。大部分服务商(如阿里云,腾讯云,京东云等)的CDN服务是按使用量收…

【iOS】-- GET和POST(NSURLSession)

文章目录 NSURLSessionGET和POST区别 GET方法GET请求步骤 POSTPOST请求步骤 NSURLSessionDataDelegate代理方法AFNetWorking添加头文件GETPOST第一种第二种 NSURLSession 使用NSURLSession,一般有两步操作:通过NSURLSession的实例创建task;执…

STL配接器(容器适配器)—— stack 的介绍使用以及模拟实现。

注意 : 以下所有文档都来源此网站 : http://cplusplus.com/ 一、stack 的介绍和使用 stack 文档的介绍:https://cplusplus.com/reference/stack/stack/ 1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中&…

预训练模型之BERT、Transformer-XL、XL-Net等

文章目录 预训练模型(Pre-trained Models, PTMs)前置知识BERTTransformer-XLXLNetTransformer-XL类似工作(Scalable Transformer)1. 《Scaling Transformer to 1M tokens and beyond with RMT》2. 《》 预训练模型(Pre…

【Linux常见指令以及权限理解】基本指令(3)

写在前面 上一篇文章,我们学习了Linux的一些常用指令, 学习了如何理解Linux系统,介绍了对Linux系统的理解:Linux下一切皆文件 介绍了重定向还有管道相关的知识。这里是上一篇博客的链接:http://t.csdn.cn/2d6fc 接…

Vue组件化编程

2.1. 模块与组件、模块化与组件化 模块: 理解:向外提供特定功能的 js 程序,一般就是一个 js 文件为什么:js 文件很多很复杂作用:复用、简化 js 的编写,提高 js 运行效率 组件: 定义&#xff…

QT界面开发杂记(五)

QString转char* QString("name").toStdString().c_str() c_str()没有‘\0’结尾可能导致一些错误可以使用以下方法解决: QString xmlPath "path"; const char cXmlName[1024] {0}; memcpy((void*)cXmlName,xmlPath.toStdStri…