redis缓存击穿

article/2025/8/25 21:57:29

缓存击穿:

缓存击穿是指,针对某个访问非常频繁的热点数据的请求,无法在缓存中进行处理,紧接着,访问该数据的大量请求,一下子都发送到了后端数据库,导致了数据库压力激增,会影响数据库处理其他请求。

原因:缓存击穿的情况,经常发生在热点数据过期失效时

解决方法

使用redis缓存

 

优点

设计简单,开发效率高
不会侵入业务代码,spring的aop就能很好的实现

缺点

一旦redis的数据失效,那么假如这时候有10w个请求打过来,由于redis没有缓存,那么按照缓存设计的逻辑,就会全部去查数据库

适用情况

如果一个系统是内部系统,天生没有太多的用户量,而某个接口需要非常耗时的查询,而数据变化又不会太频繁,就比较适用这种设计, 没有太多用户,就不会造成缓存失效的时候大量请求压到数据库的问题

定时任务主动刷新缓存设计

 

 

优点

1、用户的请求压力永远不会直接打到数据库上
2、查询redis的内存数据,查询效率很高

缺点

1、可能对redis内存消耗非常大,因为要提前将数据加载到缓存
增加了系统的复杂度,必须要有个非常可靠的定时任务操作,不然一旦定时任务失效,那么redis中的数据失效,对于用户来说就是服务不可用
数据的实时性非常依赖定时任务的执行频率,定时任务执行的频率高,实时性就强
2、数据不能保证实时刷新,如果刷新缓存的间隔设置很长,那么数据实时性就不够好,如果刷新缓存的间隔很短,那么频繁的全量刷数据库到缓存对系统和数据库都是压力,也会让数据库和应用服务器的负载变得不够平稳
3、由于是只查询缓存,所以会对业务代码进行较大程度的改动,后期业务变化,可能会非常难以维护

适用情况

1、已有一套现成的高可靠分布式定时任务系统
2、查询的数据变化不大
3、用户的请求量非常大的情况下

使用redis的分布式锁

 

查询逻辑

如果缓存命中直接返回数据集
如果缓存没有,则尝试获取分布式锁(有超时设置)
如果没有拿到锁,则阻塞当前线程,n秒,之后再次尝试获取分布式锁(自旋,轮询,浪费CPU)
拿到锁之后检查数据是否已经被其他线程放到redis缓存中,如果redis缓存已有,直接返回redis中的数据,释放分布式锁
如果缓存没有被刷新,则查数据库
将数据库查询的结果保存到redis缓存中
返回查询结果

优点

1、数据的实时性较高,不需要其他外部系统依赖,利用了redis自己的特性,实现分布式锁,保证了同样的数据库查询同时只会查询1次,对数据库的压力较小
2、不会侵入业务代码,spring的aop就能很好的实现

缺点

1、由于阻塞等待分布式锁是个自旋阻塞操作,所以其实对应用服务器来说非常浪费cpu的分片时间,如果这时候大量请求打过来, 应用服务器反而会先扛不住,因为这里会有大量的线程在自旋占用CPU,如果用户的查询是由多个系统的结果构成,每个系统的查询依赖上一个系统查询的结果,各个查询是串行的,那么自旋的睡眠时间可能会成为拖慢请求的罪魁祸首,多个系统都这么设计都在自旋睡眠,明显效率很低

适用情况

如果要求保证数据库的压力特别小,同样的请求只能查询一次数据库,
而且服务器较多,足以将多个请求分散到不同服务器,不至于造成太多线程自旋,那么可以使用这样的设计,但不推荐,因为这种自旋操作真的不是个好设计

普通加jvm的锁查询缓存

查询逻辑

如果缓存命中直接返回数据集
如果缓存没有,则尝试JVM锁,其他线程阻塞
拿到锁之后,检查redis是否有数据,以免其他线程已经刷过缓存
如果redis已经有数据,直接返回,并释放锁,返回数据库结束
如果redis没有数据,则查询数据库,并保存到redis缓存中
返回数据,释放锁
设有s台服务器,用户请求数为n
那么同一时间参数相同的请求最多只会有s次查询打到数据库上,这里s这个常量
相当于原来对于数据库来说一个O(n)的操作时间下降到了O(s)
这里可以看出,查询数据库操作的耗时与n的增长无关,只与s有关

想象一下,我们有4台服务器,本来打到数据库上可能有10w个查询,但是因为我们使用了jvm的锁,每台服务器只会查询一次,总的数据库查询次数下降到了4次,是不是很高效?而且jvm提供的锁一定比redis分布式锁自旋轮询高效太多!

优点

1、数据的实时性较高
相对于使用redis分布式锁,大幅降低服务器资源的消耗,jvm的锁效率要高很多
2、对于数据库的消耗较小,是一个和服务器数量s相关的耗时操作,与请求数量n无关(n可能会很大,十万,百万级别,而s可能最多两位数)
如果mysql数据库版本较低,说不定还能利用上mysql数据库的缓存,如果是个不频繁更新的表,运气好的情况下s-1次的查询可能都会命中mysql的缓存
3、实现的复杂度低
4、不会侵入业务代码,spring的aop就能很好的实现

缺点

1、对数据库查询虽然减小到了一个只与服务器数量相关的函数,但依然有冗余(其实也还好了)

适用情况

如果能容忍较少次数的数据库重复查询
这种设计就用这种就已经能很好的解决缓存穿透的问题了,而且设计简单复杂度低
复杂度低意味着系统的稳定

jvm缓存+redis缓存的多级缓存

 

查询的逻辑如图所示

二级缓存的关键在于:

jvm的缓存时间是个随机值,比如 10秒~30秒
这种设计,服务器只会在jvm缓存失效,且redis缓存也失效的情况下才会查询数据库,而多个服务器的jvm缓存失效时间是随机值,所以很大程度上避免的同时失效去查库的情况,由于所有服务器jvm缓存同时失效redis缓存也失效的可能性极低,所以数据库上重复的查询会很少
(不一定是jvm缓存和jvm的锁啊,python,go同理)
设服务器的台数为s

如何让O(s)的问题其变为O(1)呢?其实也是有办法的,就是多级缓存
就是让每台服务器上加一个jvm的缓存在redis之前
这个jvm的缓存时间需要设置一个随机值,比如 缓存时间为 5s-10s,这样可以很大程度避免在redis失效的时候,每台服务器都需要去做更新redis缓存的操作,因为每个服务器的jvm缓存失效时间是不一样的

优点

1、数据的实时性较高 (设置合适的jvm缓存过期时间和redis缓存过期时间)
2、几乎没有冗余的数据库查询
3、绝大多数查询是使用的jvm缓存,效率极高
4、对cpu的占用很低
5、不会侵入业务代码,spring的aop就能很好的实现

缺点

1、如果查询的参数离散度较高,其实会很浪费业务服务器的内存空间(但是可以通过减少jvm缓存的时间来优化一点)
2、设计稍微有点复杂,需要有经验的工程师来实现

适用情况

几乎可以支持所有情况,强力推荐

 


http://chatgpt.dhexx.cn/article/1tdpeNCZ.shtml

相关文章

【缓存】缓存穿透、缓存击穿、缓存雪崩及其解决方案

文章目录 缓存穿透缓存击穿缓存雪崩大量数据同时过期Redis 故障宕机 总结来源 用户的数据一般都是存储于数据库,数据库的数据是落在磁盘上的,磁盘的读写速度可以说是计算机里最慢的硬件了。 当用户的请求,都访问数据库的话,请求数…

Redis 缓存击穿,缓存穿透,缓存雪崩原因+解决方案

一、前言 在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者…

Redis缓存击穿、雪崩、穿透!(超详细)

缓存的击穿、穿透和雪崩应该是再熟悉不过的词了,也是面试常问的高频试题。 不过,对于这三大缓存的问题,有很多人背过了解决方案,却少有人能把思路给理清的。 而且,网络上仍然充斥着,大量不太靠谱的解决方案…

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

参考连接:redis避免缓存穿透为什么缓存空对象而不是null? - 知乎 缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的…

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

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

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

文章目录 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地址] 补充说明:执行…