应对缓存击穿的解决方法

article/2025/8/25 21:55:38

一.什么样的数据适合缓存?

分析一个数据是否适合缓存,我们要从访问频率、读写比例、数据一致性等要求去分析. 
这里写图片描述

二.什么是缓存击穿

在高并发下,多线程同时查询同一个资源,如果缓存中没有这个资源,那么这些线程都会去数据库查找,对数据库造成极大压力,缓存失去存在的意义.打个比方,数据库是人,缓存是防弹衣,子弹是线程,本来防弹衣是防止子弹打到人身上的,但是当防弹衣里面没有防弹的物质时,子弹就会穿过它打到人身上. 
这里写图片描述

三.缓存击穿的解决办法

方案一

后台刷新

后台定义一个job(定时任务)专门主动更新缓存数据.比如,一个缓存中的数据过期时间是30分钟,那么job每隔29分钟定时刷新数据(将从数据库中查到的数据更新到缓存中).

  • 这种方案比较容易理解,但会增加系统复杂度。比较适合那些 key 相对固定,cache 粒度较大的业务,key 比较分散的则不太适合,实现起来也比较复杂。

方案二

检查更新

将缓存key的过期时间(绝对时间)一起保存到缓存中(可以拼接,可以添加新字段,可以采用单独的key保存..不管用什么方式,只要两者建立好关联关系就行).在每次执行get操作后,都将get出来的缓存过期时间与当前系统时间做一个对比,如果缓存过期时间-当前系统时间<=1分钟(自定义的一个值),则主动更新缓存.这样就能保证缓存中的数据始终是最新的(和方案一一样,让数据不过期.)

  • 这种方案在特殊情况下也会有问题。假设缓存过期时间是12:00,而 11:59 
    到 12:00这 1 分钟时间里恰好没有 get 请求过来,又恰好请求都在 11:30 分的时 
    候高并发过来,那就悲剧了。这种情况比较极端,但并不是没有可能。因为“高 
    并发”也可能是阶段性在某个时间点爆发。

方案三

分级缓存

采用 L1 (一级缓存)和 L2(二级缓存) 缓存方式,L1 缓存失效时间短,L2 缓存失效时间长。 请求优先从 L1 缓存获取数据,如果 L1缓存未命中则加锁,只有 1 个线程获取到锁,这个线程再从数据库中读取数据并将数据再更新到到 L1 缓存和 L2 缓存中,而其他线程依旧从 L2 缓存获取数据并返回。

  • 这种方式,主要是通过避免缓存同时失效并结合锁机制实现。所以,当数据更 
    新时,只能淘汰 L1 缓存,不能同时将 L1 和 L2 中的缓存同时淘汰。L2 缓存中 
    可能会存在脏数据,需要业务能够容忍这种短时间的不一致。而且,这种方案 
    可能会造成额外的缓存空间浪费。

方案四

加锁

方法1

    // 方法1:public synchronized List<String> getData01() {List<String> result = new ArrayList<String>();// 从缓存读取数据result = getDataFromCache();if (result.isEmpty()) {// 从数据库查询数据result = getDataFromDB();// 将查询到的数据写入缓存setDataToCache(result);}return result;}
  • 这种方式确实能够防止缓存失效时高并发到数据库,但是缓存没有失效的时候,在从缓存中拿数据时需要排队取锁,这必然会大大的降低了系统的吞吐量.

方法2

// 方法2:static Object lock = new Object();public List<String> getData02() {List<String> result = new ArrayList<String>();// 从缓存读取数据result = getDataFromCache();if (result.isEmpty()) {synchronized (lock) {// 从数据库查询数据result = getDataFromDB();// 将查询到的数据写入缓存setDataToCache(result);}}return result;}
  • 这个方法在缓存命中的时候,系统的吞吐量不会受影响,但是当缓存失效时,请求还是会打到数据库,只不过不是高并发而是阻塞而已.但是,这样会造成用户体验不佳,并且还给数据库带来额外压力.

方法3

//方法3public List<String> getData03() {List<String> result = new ArrayList<String>();// 从缓存读取数据result = getDataFromCache();if (result.isEmpty()) {synchronized (lock) {//双重判断,第二个以及之后的请求不必去找数据库,直接命中缓存// 查询缓存result = getDataFromCache();if (result.isEmpty()) {// 从数据库查询数据result = getDataFromDB();// 将查询到的数据写入缓存setDataToCache(result);}}}return result;}

双重判断虽然能够阻止高并发请求打到数据库,但是第二个以及之后的请求在命中缓存时,还是排队进行的.比如,当30个请求一起并发过来,在双重判断时,第一个请求去数据库查询并更新缓存数据,剩下的29个请求则是依次排队取缓存中取数据.请求排在后面的用户的体验会不爽.

方法4

static Lock reenLock = new ReentrantLock();public List<String> getData04() throws InterruptedException {List<String> result = new ArrayList<String>();// 从缓存读取数据result = getDataFromCache();if (result.isEmpty()) {if (reenLock.tryLock()) {try {System.out.println("我拿到锁了,从DB获取数据库后写入缓存");// 从数据库查询数据result = getDataFromDB();// 将查询到的数据写入缓存setDataToCache(result);} finally {reenLock.unlock();// 释放锁}} else {result = getDataFromCache();// 先查一下缓存if (result.isEmpty()) {System.out.println("我没拿到锁,缓存也没数据,先小憩一下");Thread.sleep(100);// 小憩一会儿return getData04();// 重试}}}return result;}
  • 最后使用互斥锁的方式来实现,可以有效避免前面几种问题.

当然,在实际分布式场景中,我们还可以使用 redis、tair、zookeeper 等提供的分布式锁来实现.但是,如果我们的并发量如果只有几千的话,何必杀鸡焉用牛刀呢?

 


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

相关文章

redis缓存击穿

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

一、概述 ① 缓存穿透&#xff1a;大量请求根本不存在的key&#xff08;下文详解&#xff09; ② 缓存雪崩&#xff1a;redis中大量key集体过期&#xff08;下文详解&#xff09; ③ 缓存击穿&#xff1a;redis中一个热点key过期&#xff08;大量用户访问该热点key&#xff0c;…

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

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

ping端口

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

windows下ping端口

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

windows ping 端口测试

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

Windows Server 启用或关闭ping端口

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

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

第一步&#xff1a; 第二步&#xff1a;打开telnet client 第三步&#xff1a;telnet ip 端口

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

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