缓存穿透、缓存击穿、缓存雪崩如何应对

article/2025/8/26 2:07:42

 参考连接:redis避免缓存穿透为什么缓存空对象而不是null? - 知乎

  • 缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。
  • 缓存击穿:key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
  • 缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。

1. 缓存穿透解决思路:

1.1 校验参数

我们可以对用户id做检验。

比如你的合法id是15xxxxxx,以15开头的。如果用户传入了16开头的id,比如:16232323,则参数校验失败,直接把相关请求拦截掉。这样可以过滤掉一部分恶意伪造的用户id。

1.2 布隆过滤器

如果数据比较少,我们可以把数据库中的数据,全部放到内存的一个map中。

这样能够非常快速的识别,数据在缓存中是否存在。如果存在,则让其访问缓存。如果不存在,则直接拒绝该请求。

但如果数据量太多了,有数千万或者上亿的数据,全都放到内存中,很显然会占用太多的内存空间。

那么,有没有办法减少内存空间呢?

答:这就需要使用布隆过滤器了。

布隆过滤器底层使用bit数组存储数据,该数组中的元素默认值是0。

布隆过滤器最致命的问题是:如果数据库中的数据更新了,需要同步更新布隆过滤器。但它跟数据库是两个数据源,就可能存在数据不一致的情况。

1.3 缓存空值

上面使用布隆过滤器,虽说可以过滤掉很多不存在的用户id请求。但它除了增加系统的复杂度之外,会带来两个问题:

  1. 布隆过滤器存在误杀的情况,可能会把少部分正常用户的请求也过滤了。
  2. 如果用户信息有变化,需要实时同步到布隆过滤器,不然会有问题。

所以,通常情况下,我们很少用布隆过滤器解决缓存穿透问题。其实,还有另外一种更简单的方案,即:缓存空值

当某个用户id在缓存中查不到,在数据库中也查不到时,也需要将该用户id缓存起来,只不过值是空的。这样后面的请求,再拿相同的用户id发起请求时,就能从缓存中获取空数据,直接返回了,而无需再去查一次数据库。

作者:苏三说技术
链接:https://www.zhihu.com/question/329377564/answer/2286917807
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 

2. 缓存击穿问题

2.1 什么是缓存击穿?

有时候,我们在访问热点数据时。比如:我们在某个商城购买某个热门商品。

为了保证访问速度,通常情况下,商城系统会把商品信息放到缓存中。但如果某个时刻,该商品到了过期时间失效了。

此时,如果有大量的用户请求同一个商品,但该商品在缓存中失效了,一下子这些用户请求都直接怼到数据库,可能会造成瞬间数据库压力过大,而直接挂掉。

流程图如下:

那么,如何解决这个问题呢?

2.2 加锁

数据库压力过大的根源是,因为同一时刻太多的请求访问了数据库。

如果我们能够限制,同一时刻只有一个请求才能访问某个productId的数据库商品信息,不就能解决问题了?

答:没错,我们可以用加锁的方式,实现上面的功能。

伪代码如下:

try {String result = jedis.set(productId, requestId, "NX", "PX", expireTime);if ("OK".equals(result)) {return queryProductFromDbById(productId);}
} finally{unlock(productId,requestId);
}  
return null;

在访问数据库时加锁,防止多个相同productId的请求同时访问数据库。

然后,还需要一段代码,把从数据库中查询到的结果,又重新放入缓存中。办法挺多的,在这里我就不展开了。

2.3 自动续期

出现缓存击穿问题是由于key过期了导致的。那么,我们换一种思路,在key快要过期之前,就自动给它续期,不就OK了?

答:没错,我们可以用job给指定key自动续期。

比如说,我们有个分类功能,设置的缓存过期时间是30分钟。但有个job每隔20分钟执行一次,自动更新缓存,重新设置过期时间为30分钟。

这样就能保证,分类缓存不会失效。

此外,在很多请求第三方平台接口时,我们往往需要先调用一个获取token的接口,然后用这个token作为参数,请求真正的业务接口。一般获取到的token是有有效期的,比如24小时之后失效。

如果我们每次请求对方的业务接口,都要先调用一次获取token接口,显然比较麻烦,而且性能不太好。

这时候,我们可以把第一次获取到的token缓存起来,请求对方业务接口时从缓存中获取token。

同时,有一个job每隔一段时间,比如每隔12个小时请求一次获取token接口,不停刷新token,重新设置token的过期时间。

2.4 缓存不失效

此外,对于很多热门key,其实是可以不用设置过期时间,让其永久有效的。

比如参与秒杀活动的热门商品,由于这类商品id并不多,在缓存中我们可以不设置过期时间。

在秒杀活动开始前,我们先用一个程序提前从数据库中查询出商品的数据,然后同步到缓存中,提前做预热

等秒杀活动结束一段时间之后,我们再手动删除这些无用的缓存即可。

3. 缓存雪崩问题

3.1 什么是缓存雪崩?

前面已经聊过缓存击穿问题了。

而缓存雪崩是缓存击穿的升级版,缓存击穿说的是某一个热门key失效了,而缓存雪崩说的是有多个热门key同时失效。看起来,如果发生缓存雪崩,问题更严重。

缓存雪崩目前有两种:

  1. 有大量的热门缓存,同时失效。会导致大量的请求,访问数据库。而数据库很有可能因为扛不住压力,而直接挂掉。
  2. 缓存服务器down机了,可能是机器硬件问题,或者机房网络问题。总之,造成了整个缓存的不可用。

归根结底都是有大量的请求,透过缓存,而直接访问数据库了。

那么,要如何解决这个问题呢?

3.2 过期时间加随机数

为了解决缓存雪崩问题,我们首先要尽量避免缓存同时失效的情况发生。

这就要求我们不要设置相同的过期时间。

可以在设置的过期时间基础上,再加个1~60秒的随机数。

实际过期时间 = 过期时间 + 1~60秒的随机数

这样即使在高并发的情况下,多个请求同时设置过期时间,由于有随机数的存在,也不会出现太多相同的过期key。

3.3 高可用

针对缓存服务器down机的情况,在前期做系统设计时,可以做一些高可用架构。

比如:如果使用了redis,可以使用哨兵模式,或者集群模式,避免出现单节点故障导致整个redis服务不可用的情况。

使用哨兵模式之后,当某个master服务下线时,自动将该master下的某个slave服务升级为master服务,替代已下线的master服务继续处理请求。

3.4 服务降级

如果做了高可用架构,redis服务还是挂了,该怎么办呢?

这时候,就需要做服务降级了。

我们需要配置一些默认的兜底数据。

程序中有个全局开关,比如有10个请求在最近一分钟内,从redis中获取数据失败,则全局开关打开。后面的新请求,就直接从配置中心中获取默认的数据。

当然,还需要有个job,每隔一定时间去从redis中获取数据,如果在最近一分钟内可以获取到两次数据(这个参数可以自己定),则把全局开关关闭。后面来的请求,又可以正常从redis中获取数据了。

参考连接:redis避免缓存穿透为什么缓存空对象而不是null? - 知乎


http://chatgpt.dhexx.cn/article/vDlNCd4a.shtml

相关文章

缓存穿透、缓存击穿、缓存雪崩区别和解决方案

一、缓存处理流程 前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。 二、缓存穿透 描述: …

缓存穿透,缓存雪崩,缓存击穿的超详解

文章目录 1、缓存穿透问题的解决思路2、缓存雪崩问题及解决思路3、缓存击穿问题及解决思路 1、缓存穿透问题的解决思路 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库,失去了缓存的…

redis 缓存穿透,缓存击穿,缓存雪崩

虽然我们在使用 redis 缓存的时候非常的爽,它大大的提高了我们应用程序的性能和效率,尤其是数据查询方面,咱们不用直接去持久化的数据库中查询数据,而是到内存中查询数据即可 事物总是有两面的,用的爽的同时&#xff…

缓存穿透、缓存击穿、缓存雪崩的理解和解决方案

目录 一、缓存穿透 二、缓存击穿 三:缓存雪崩 在生产环境中,会因为很多的原因造成访问请求绕过了缓存,都需要访问数据库持久层,虽然对Redsi缓存服务器不会造成影响,但是数据库的负载就会增大,使缓存的作…

详解缓存穿透、缓存雪崩、缓存击穿

背景 在现代软件架构中,缓存的应用已经非常普及。缓存的使用在面试和实践中都是避不开的硬技能、硬知识,如果你说还不太熟悉缓存的使用,可能都不好意思说自己是程序员。 这篇文章,带大家进一步学习在缓存使用中不得不考虑三个特…

【Redis】缓存击穿问题及其解决方案

【Redis】缓存击穿问题及其解决方案 文章目录 【Redis】缓存击穿问题及其解决方案1. 缓存击穿概念2. 解决方案2.1 互斥锁2.1.1 互斥锁的优缺点2.1.2 互斥锁的代码实现 2.2 逻辑过期2.2.1 逻辑过期的优缺点2.2.2 逻辑过期的代码实现 1. 缓存击穿概念 缓存击穿:缓存击…

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

文章目录 一、缓存穿透1. 概念2. 解决方案 二、缓存击穿1. 概念2. 解决方案 三、缓存雪崩1. 概念2. 解决方案 一、缓存穿透 1. 概念 key 对应的数据在redis中并不存在,每次针对此 key的请求从缓存获取不到,请求转发到数据库,访问量大了可能…

Redis中的缓存穿透、雪崩、击穿的原因以及解决方案(详解)

一、概述 ① 缓存穿透:大量请求根本不存在的key(下文详解) ② 缓存雪崩:redis中大量key集体过期(下文详解) ③ 缓存击穿:redis中一个热点key过期(大量用户访问该热点key,…

Redis——缓存击穿、穿透、雪崩

1、缓存穿透: (1)问题描述:key对应的数据并不存在,每次请求访问key时,缓存中查找不到,请求都会直接访问到数据库中去,请求量超出数据库时,便会导致数据库崩溃。如一个用…

ping端口

1.ping端口: telnet 62.78.63.209 10105 2.如果提示telnet不是内部或外部命令… 则:右击“此电脑”–>选择“控制面板主页”,单击“程序”,如图: 3.完成。

windows下ping端口

上图的操作完成以后 进入dos控制台 输入telnet ip地址 端口号 回车 标识已ping通 ping不通是这种提示 转载于:https://www.cnblogs.com/shianliang/p/8639392.html

windows ping 端口测试

前言 项目中存在能ping通IP地址,但是打不开web应用程序,这时需要测试端口能否ping通。 解决方法 测试是否能够ping通192.168.0.1的80端口 telnet 192.168.0.1 80遇到问题 ‘telnet’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。 …

Windows Server 启用或关闭ping端口

启用或关闭 ping 端口有两种方式,如下 1、通过命令行设置 打开 ping 端口 netsh firewall set icmpsetting 8关闭 ping 端口 netsh firewall set icmpsetting 8 disable2、通过高级安全 Windows 防火墙设置 打开 “高级安全 Windows 防火墙” ,在入…

windows系统ping端口及利用telnet命令Ping 端口

第一步: 第二步:打开telnet client 第三步:telnet ip 端口

Mac系统用命令打开ping端口的方法

电脑上不了网问题相信大家都有遇到过,排查网络故障问题用到ping,之前windows系统上能够轻松打开ping端。但是如果在Mac电脑该如何打开ping端口?其实打开方法并不复杂,接下来小编给大家演示Mac系统用命令打开ping端口的方法。 Mac…

linux ping 某个端口,linux 怎么ping 端口

满意答案 cysdmt 推荐于 2016.12.05 采纳率:54% 等级:8 已帮助:864人 linux命令ping用法详解 功能说明:检测主机。 语 法:ping [-dfnqrrv][-c][-i][-i][-l][-p][-s][-t][主机名称或ip地址] 补充说明:执行…

Win10系统Ping端口及利用telnet命令Ping 端口

启用 telnet 客户端组件为 Ping 端口做准备 在程序界面下,选择“打开或关闭Windows功能”,如下图所示: 在打开的对话框中,找到“Telnet客户端”并勾选。最后点击“确定”,等待几分钟,系统将会为你开启Teln…

计算机ping使用的端口,mac系统ping端口命令怎么使用

最近电脑出问题了,上不了网,想排查下电脑的问题出在哪儿就需要ping,但是该如何打开终端如何ping呢?下面就让学习啦小编教大家MAC系统ping端口命令怎么使用吧。 Mac系统ping端口命令的使用方法 方法一: 在桌面上的DOCK栏中&#x…

w7系统怎么ping服务器,win7系统中如何ping端口命令

正常情况下,win7系统时无法ping端口的,不过要是开启了Telnrt客户端,则可以实现这一功能,启用Telnrt客户端需要用户进入Windows 组件中勾选,当然,如果用户有一个可以专门Ping端口的第三方软件也是可以的。 一…

Win10如何ping端口是否开放

如何ping端口是否开放 前言一、打开Telent Client功能1.打开控制面板2.进入启用Windows功能页面,勾选Telnet客户端3.打开cmd,输入命令 telnet ip 端口4.回车如果进入黑屏页面,则ping通了,否则显示连接失败 前言 ping具体的网址是…