阿里面试Redis最常问的三个问题:缓存穿透、缓存击穿、缓存雪崩(带答案)

news/2024/11/28 23:47:21/

一、缓存穿透

如上图,正常情况下,如果用户在redis缓存中没有查询到自己想要的数据,就会去mysql数据库中查询。如果mysql数据库中也没有,在没有任何措施下,用户一定会不断的去mysql数据库中查询,随着时间的推移,用户越来越多,越来越多的用户在redis缓存中没有查询到自己想要的数据,越来越多的用户就会去mysql数据库中查询,这就造成了缓存穿透。

解决方案:

1、使用布隆过滤器

“过滤器”这个名词做过项目的人应该很熟悉,而对于redis缓存穿透而言,使用“布隆过滤器”就是解决方案之一。

后台服务端可以在用户和redis数据库之间搭上一个“过滤器”,在用户访问redis之前,通过布隆过滤器,如果用户想访问的数据在redis数据库中没有的话,就使用布隆过滤器将用户的这次访问给过滤掉,这样的话用户就不会再去访问mysql数据库了,很好的解决了缓存穿透。

2、redis缓存空值(占空间,没意义,不建议)

当用户访问redis的时候,如果说用户访问的数据在redis中没有,那就根据用户访问的“key”给用户在redis中缓存一个空的“value”,这样的话用户就不用再去访问mysql数据库了。

这种方法也是解决缓存穿透的一种方案,但是不建议。因为在redis中缓存一个空的value,一方面占了redis数据库的空间(redis数据库的数据是存在内存中的,而内存又有限),另一方面给一个key缓存一个空的value也没有什么意义,而且还浪费数据库开销,所以这种方案不建议。

二、缓存击穿

当某一个“key”的热度非常高,肯定就会有很多的人根据这个“key”去redis中查询对应的“value”。

刚才也说过,因为redis数据是存在内存中的,内存又有限,所以redis会对于一些数据设置过期时间,一到时间,这些key就会过期消失。

所以如果当某个热度很高的“key”在redis中过期了,那么这些用户肯定会集体的去访问mysql数据库(就像一颗颗子弹,全部都打到了一个点上),因此就造成了缓存击穿。

缓存击穿和缓存穿透很像,但是还是有一些区别的。

解决方案:

1、设置热点数据永不过期

这是一个很绝的方案,可以完美的解决缓存击穿。

但是不建议,因为redis本就内存有限,热点数据越来越多,无疑就会撑满redis,导致redis的性能下降。总的来说就是“占空间”。

2、加互斥锁

某个热点“key”突然失效过期,用户们在redis中访问无果,肯定会集体去mysql访问。

而在用户们访问mysql之间就可以加一道锁,来解决缓存击穿。

加锁只保证一个线程可以进去,这样的话就可以解决大量的用户去mysql访问同一个数据。

三、缓存雪崩

缓存雪崩是最好理解的,雪崩的场景大家肯定都不陌生。

当某个时间段,redis缓存中的“key”集体失效(可以理解为redis宕机),那么用户查不到这些“key”对应的“value”,就肯定会集体的向mysql数据库中查询,这样大面积的访问,就造成了缓存雪崩。

和缓存击穿很像,但是又不一样,缓存击穿是大量的用户去mysql中查询同一个“key”对应的“value”,而缓存雪崩是大量的用户去mysql中查询不同“key”对应的“value”。

解决方案:

1、实现redis高可用

搭建redis集群,配置redis哨兵机制,实现redis高可用。

主机宕机之后,通过redis哨兵机制去自动的在从机中重新选取主机,实现redis的高可用,解决缓存雪崩。

2、数据预热

可以把可能会大量访问的数据预先访问一遍,然后在加载到缓存中,最后再给它们设置不同的缓存过期时间,让缓存失效的时间点尽量均匀一些。这也是解决缓存雪崩的一种方案。


http://www.ppmy.cn/news/2530.html

相关文章

在地图上基于OpenLayers实现点/线/面静态的绘制显示

在做GIS相关的工作过程中,是离不开矢量的数据的。矢量作为最基础的数据形式,一般通用在各个项目中。在导航软件开发或者应用中,点/线/面的标记,标绘,显示等都是不可缺少的。本文主要是来介绍在地图上基于OpenLayers实现…

RemoteServiceException: can‘t deliver broadcast 问题分析

一、问题背景 最近测试跑monkey报了一个应用崩溃的log,核心堆栈如下(已脱敏,出问题的android系统版本是api11,AndroidR): ps: 本次涉及的应用包名统一用com.my.app代替 11-28 03:57:20.326 12039 12039 E …

win11摄像头黑了用不了的七个解决办法

目录 前言必读 方法一、重置和隐式设置摄像头 方法二、更新windwos驱动 方法三、检查串行总线控制器 方法四、下载驱动精灵来安装驱动 方法五、驱动精灵里面修复 方法六、检查键盘上面有没有物理摄像头按键 方法七、使用万能摄像头 前言必读 读者手册(必读&…

给你讲明白MySQL的乐观锁和悲观锁

乐观锁与悲观锁是一种广义上的概念。不管是 Java 语言,也或者是其他语言以及数据库都有这类概念对应的实际应用。想要学习乐观锁和悲观锁就要学习他们的基本知识,那么下面我们来学习一下。 锁 生活中:锁在我们身边无处不在,比如我…

【Zookeeper】学习笔记(二)

Zookeeper学习笔记四、客户端命令4.1、新增节点4.2、查询节点信息4.3、节点类型4.4、更新节点4.5、删除节点4.6、监听器五、SpringBOOT整合Zookeeper六、写数据流程6.1、写流程之写入请求直接发送给Leader节点6.2、写流程之写入请求发送给follower节点七、服务器动态上下线监听…

Spring从入门到精通(二)

文章目录1.动态代理1.1 概念1.2 jdk动态代理(重点)1.3 基于子类的动态代理(了解)2.AOP2.1 概念2.2 springAop — 基于AspectJ技术2.2.1 AspectJ使用(XML)2.2.2 AspectJ使用(注解开发&#xff09…

c语言---指针进阶(2)--玩转指针

今天内容不多,但都是精华。 1.数组参数和指针参数 2.函数指针 2.1笔试题 3.函数指针数组 1.数组参数和指针参数 例1:一维数组传参 void test(int arr[]) {} void test(int arr[10]) {} void test(int *arr) {}void test2(int *arr2[20]) {} void …

Verilog语法之generate for、generate if、generate case

0、前言 Verilog-2005中有3个generate 语句可以用来很方便地实现重复赋值和例化(generate for)或根据条件选择性地进行编译(generate if和generate case)等功能。接下来就一起看下这3个语句的应用场景和应用方法吧。 1、generate …