高薪offer收割面试题之缓存穿透,击穿,雪崩

news2024/11/27 22:17:19

缓存穿透,缓存击穿,缓存雪崩是我们在应用缓存时最常碰到的问题,也是面试的热点考点。究竟什么是缓存穿透,缓存击穿,缓存雪崩,如何解决,本文会进行详细的剖析。

缓存穿透

什么是缓存穿透,我们通过一个例子来说明:

现在有这样一个需求需要根据文章id来查询文章信息,正常流程是先在Redis缓存中查找,如果找到了直接返回,找不到则到mysql数据库中查找,此时有两种情况:

1.数据库中查找到了将数据库中查找到的文章信息放入Redis缓存之后返回。

2.数据库中也没有查找到,这种情况下,每次查询该id的文章都会绕过Redis缓存直接到mysql数据库中查询,如果在短时间内发起大量查询可能导致数据库崩溃,这就是缓存穿透。

如何解决缓存穿透呢?

解决缓存穿透通常有两种方案:

第一种方案:缓存空数据

也就是虽然在数据库中查找不到该id的文章,也把该文章的信息缓存起来,只是缓存的为空值,这样以后每次查询这个id的文章就可以在缓存中命中,虽然值为空。

这种解决方案虽然可以解决数据库被压垮的问题,但是如果需要缓存的空值很多会导致内存消耗过大。

另外如果在数据库中已经插入了该记录而缓存中依然为空会导致缓存与数据库中的数据不一致。

第二种方案:使用布隆过滤器

从上图可以看出在查询缓存之前会先查询布隆过滤器,在布隆过滤器中判断该id的文章是否存在,如果存在继续查询Redis缓存,不存在则直接返回,这样请求就没有机会继续查询Redis缓存和mysql数据库。

究竟什么是布隆过滤器,它的工作原理又是什么呢?

布隆过滤器就是一个以位(bit)为单位的数组,数组中的每个元素只能存储二进制的0或者1,它的作用是检索一个元素是否在一个集合中。

布隆过滤器的工作原理

初始化位数组

初始状态下布隆过滤器中的元素都是0.

从数据库中查询出所有的key(即id)将这些key添加到布隆过滤器。

添加key时

使用多个hash函数对key进行hash运算得到一个整数值,对位数组长度进行取模运算得到一个位置,每个hash函数都会得到一个不同的位置,将这几个位置都置1就完成了添加操作。

判断是否存在

从布隆过滤器查询某个key是否存在时,先用添加key时的hash函数对这个key进行计算,查看布隆过滤器的位数组中对应的位置是否都为 1,只要有一个位为零,那么说明布隆过滤器中这个 key 不存在.如果这几个位置全都是 1,那么说明极有可能存在.因为这些位置的 1 可能是因为其他的 key 存在导致的。

可以看出使用布隆过滤器可以准确的判断出某key不存在,但是不能完全准确的判断其存在,有一定的误判率,不过该误判率对实际应用影响不大。

总结:使用布隆过滤器解决缓存穿透问题的优点是内存占用少,缺点是实现复杂而且存在一定概率的误判。

缓存击穿

什么是缓存击穿?


缓存击穿就是给缓存的某一个key设置了过期时间,当这个key过期而缓存重建还没有完成的时候有大量的请求过来,直接打在数据库上把数据库压垮。

有两种方案可以解决缓存击穿

第一种:互斥锁

如图所示,当线程一查询缓存没有命中的时候他会获取一个互斥锁,然后再去查询数据库重建缓存数据,此时线程二也来查询缓存当它获取互斥锁的时候失败于是等待重试直到线程一释放互斥锁线程二可以查询到缓存中的值。

通过加入互斥锁保证在缓存过期的时间段内只有一个线程能去访问数据库从而解决了缓存击穿。

这种方式虽然能够解决缓存击穿但是效率非常低,在一个线程重建缓存的过程中其它线程只能等待,再来看看第二种解决方案:

第二种:逻辑过期

我们将数据添加到缓存中去的时候不设置它的过期时间而是在缓存的数据中增加一个过期时间。

例如:{"id":"123","title":"今日暴雨","expire":153213455}

这里的"expire":153213455就是过期时间。这个过期时间不是真正的过期时间只是逻辑上的因此叫逻辑过期。

如图所示当线程1查询缓存的时候发现逻辑时间已过期,于是它获取互斥锁,之后它开启一个新的线程2,在线程2中查询数据库重建缓存,重置逻辑过期时间,一切做完以后在线程2中释放锁,而线程1在开启新线程以后立马返回过期数据。

在线程2重建缓存的过程中如果线程3也开始查询缓存,发现逻辑时间已过期,它会去获取互斥锁,因为此时互斥锁被线程2占用所以线程3获取锁失败直接返回过期数据。

这里的关键在于线程1和线程3都是直接返回的过期数据,从而避免了长时间的等待提高了程序的执行效率,但是做不到数据的强一致性

缓存雪崩

缓存雪崩是指在同一时间段,大量缓存key同时失效或者Redis服务器宕机导致大量请求打到数据库,从而压垮数据库。

解决缓存雪崩通常有这样几种方案:

  1. 给不同key的过期时间添加随机值,避免这些key在同一时间同时失效。
  2. 利用Redis的集群提高缓存服务的可用性从而避免单机服务器宕机以后带来的影响。
  3. 给缓存业务添加限流策略避免大量的请求同时过来,可以通过nginx或网关来做到。

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

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

相关文章

CUDA和CUDNN安装和版本验证

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、安装二、关键指标1.驱动版本和CUDA版本对应1.最适配版本2.最低支持版本 2.CUDA版本和CUDNN版本对应 三、验证有效性1.驱动验证2.CUDA验证1.nvcc2.sample 3.…

E. Masha-forgetful(dp)

题目:Problem - E - Codeforceshttps://codeforces.com/contest/1624/problem/E 题意: 玛莎认识了一个新朋友,并知道了他的电话号码 s 。电话号码是一个长度为m的字符串,它由从 0-9 组成 。 电话号码可能以 0 开头。 玛莎已经…

花30分钟,用Jenkins部署码云上的SpringBoot项目

本文介绍 jenkins 如何从 gitee 上 clone 项目,然后使用 maven 打包并后台启动。 1.Jenkins 介绍 Jenkins 是一个开源软件项目,是基于 Java 开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台&…

7月4号作业

实现底层实现三盏灯的控制 head.h #ifndef __HEAD_H__ #define __HEAD_H__#define PHY_LED1_MODER 0X50006000 #define PHY_LED1_ODR 0X50006014#define PHY_RCC 0X50000A28#define PHY_LED2_MODER 0X50007000 #define PHY_LED2_ODR 0X50007014#endif led.c #in…

2023年,第九届WWEC教育者大会隆重回归

2023年第九届WWEC教育者大会将于8月20日至22日在上海举行。本次大会也是时隔两年之后再度重启,是疫情恢复常态化后教育界的首次重要大会。 WWEC教育者大会由宋辉先生发起,嘉家有品主办,君学书院、雁传书文化传媒和有鹏来教育科技联合主办。本…

jdbcTemplate的queryForList报错:Incorrect column count: expected 1, actual 2

jdbcTemplate的queryForList方法有多种传参形式,我们常用的就是这种传class类,参数返回数据,结果报expected 1, actual 2,意思是预期只返回一列,但却返回了2列。这是不合理的,因为返回参数都是List&#xf…

PCL 法向量估计源码学习

一、思路&#xff1a; 二、源码 #ifndef PCL_FEATURES_IMPL_NORMAL_3D_H_ #define PCL_FEATURES_IMPL_NORMAL_3D_H_#include <pcl/features/normal_3d.h>/// template <typename PointInT, typename PointOutT> void pcl::NormalEstimation<PointInT, PointOutT…

【Matlab】智能优化算法_海洋捕食者算法MPA

【Matlab】智能优化算法_海洋捕食者算法MPA 1.背景介绍1.1 布朗运动1.2 莱维运动 2.数学模型2.1 MPA配方2.2 MPA优化场景2.3 涡流形成与FAD效应 3.文件结构4.伪代码5.详细代码及注释5.1 func_plot.m5.2 Get_Functions_details.m5.3 initialization.m5.4 levy.m5.5 main.m5.6 MP…

【H5】文件上传(ajax)

系列文章 【移动设备】iData 50P 技术规格 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/130604517 【H5】avalon前端数据双向绑定 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/131067187 【H5】安卓自动更新方案&a…

Python_装饰器

目录 简单装饰器 语法糖 *args、**kwargs处理有参数的函数 带参数的装饰器 类装饰器 不带参数的类装饰器 带参数的类装饰器 装饰器执行顺序 functools.wraps 讲 Python 装饰器前&#xff0c;我想先举个例子&#xff0c;虽有点污&#xff0c;但跟装饰器这个话题很贴切。…

select……for update 到底加的什么锁

先上结论 主键索引唯一索引普通索引普通字段等值查询行锁行锁行锁间隙锁&#xff0c;锁表范围查询间隙锁&#xff0c;锁范围行间隙锁&#xff0c;锁范围行间隙锁&#xff0c;锁范围行间隙锁&#xff0c;锁表 数据表准备 DROP TABLE IF EXISTS t_user_test; CREATE TABLE t_u…

【Web3】MetaMask钱包配置

目录 主网更换测试网 私钥如何登录钱包 主网更换测试网 私钥如何登录钱包

docker安装ES,IK分词器,Kibana

dockerhub上自己搜要拉的镜像版本 // 拉取es 6.8.0的镜像版本 docker pull elasticsearch:6.8.0// 运行es镜像 docker run -d -p 9300:9300 -p 9200:9200 --name elasticsearch elasticsearch:6.8.0运行报错了 ERROR: [1] bootstrap checks failed [1]: max virtual memory are…

Michael.W基于Foundry精读Openzeppelin第3期——Arrays.sol

Michael.W基于Foundry精读Openzeppelin第3期——Arrays.sol 0. 版本0.1 Arrays.sol 1. 补充&#xff1a;关于storage的定长数组和动态数组的layout2. 目标合约3. 代码精读3.1 unsafeAccess(address[] storage, uint256)3.2 unsafeAccess(bytes32[] storage, uint256)3.3 unsafe…

限时等待的互斥量

本文结束一种新的锁&#xff0c;称为 timed_mutex 代码如下&#xff1a; #include<iostream> #include<mutex> #include<thread> #include<string> #include<chrono>using namespace std;timed_mutex tmx;void fun1(int id, const string&a…

MySql入门操作

一.前节回顾 1.web项目环境配置 2.通用增删改&#xff0c;通用查询方法 3.前台&#xff0c;后台代码显示效果 所有你都理解了吗&#xff1f; 二.Mysql数据库介绍 1.什么是MySQL&#xff1f; MySQL是一种开源的关系型数据库管理系统。它是目前最流行和广泛使用的数据库之一&…

【Java|golang】2679. 矩阵中的和

给你一个下标从 0 开始的二维整数数组 nums 。一开始你的分数为 0 。你需要执行以下操作直到矩阵变为空&#xff1a; 矩阵中每一行选取最大的一个数&#xff0c;并删除它。如果一行中有多个最大的数&#xff0c;选择任意一个并删除。 在步骤 1 删除的所有数字中找到最大的一个…

NodeJS 后端返回Base64格式数据显示图片 ⑩⑨ (一篇就够了)

文章目录 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&#x1f618;前言Base64前端服务器总结 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&#x1f618; ⡖⠒⠒⠒⠤⢄⠀⠀⠀ …

【Java语法小记】求字符串中某个字符的数量——IntStream流的使用

文章目录 引入需求代码原理解读s.chars()IntStream filter​(IntPredicate predicate)long count()补充&#xff1a;IntStream peek​(IntConsumer action) 流操作和管道 引入需求 从一段代码引入 return s.length() - (int) s.chars().filter(c -> c S).count(); 其中 (…

文心一言 VS 讯飞星火 VS chatgpt (54)-- 算法导论6.2 6题

文心一言 VS 讯飞星火 VS chatgpt &#xff08;53&#xff09;-- 算法导论6.2 5题 六、证明:对一个大小为 n的堆&#xff0c;MAX-HEAPIFY 的最坏情况运行时间为 Ω(Ign)。(提示对于n个结点的堆&#xff0c;可以通过对每个结点设定恰当的值&#xff0c;使得从根结点到叶结点路径…