返回顶部
首页 > 资讯 > 精选 >怎么使用spring-cache代码解决缓存击穿问题
  • 654
分享到

怎么使用spring-cache代码解决缓存击穿问题

2023-06-30 09:06:14 654人浏览 八月长安
摘要

本篇内容介绍了“怎么使用spring-cache代码解决缓存击穿问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!正文目前缺陷首先,为什么说

本篇内容介绍了“怎么使用spring-cache代码解决缓存击穿问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    正文

    目前缺陷

    首先,为什么说目前网上流传的方案,落地性差呢,因为都缺乏一个可以和SpringBoot结合起来的真实场景,基本上都脱离了SpringBoot,只站在Java这个层级去分析。那问题就来了,现在还有只用springMVC,却不用SpringBoot的公司么?因此,本文尝试将该方案和SpringBoot结合起来,讲一个确实可行,可以落地的方案!

    当然,我们先来说说目前在网上流传的几套方案,到底不靠谱在哪里!

    (1)布隆过滤器

    关于布隆过滤器,我就不介绍太多,这里就理解为是一个过滤器,用于快速检索一个元素是否在一个集合中;那么当一个请求来的时候,快速判断这个请求的key是否在指定集合中!如果在,说明有效,则放行。如果不在,则无效拦截。 至于实现,各大博客也说了用了Google提供的

    <dependency>    <groupId>com.google.guava</groupId>    <artifactId>guava</artifactId>    <version>19.0</version></dependency>

    这个包里有现成写好的java类给你使用了,当然demo代码我就不贴了,一抓一大把! 当然,似乎看上去完美无暇!一切都是那么的合适!

    然而到这里,我就真的问一句,你们真的用了这个方案了?

    我如果猜的没错,应该没几个人遇到过缓存击穿问题~

    更何况,证明这个说法的正确性~

    该方案最大的一个问题是布隆过滤器不支持反向删除操作,例如你的项目里活跃的key的数量只有1000w个,但是全部key数量有5000w个,那这5000w个key会全部存在布隆过滤器里!

    直到某一天,你会发现这个过滤器太拥挤了,误判率太高,不得不进行重建!

    so,你们觉得这个做法真的靠谱?

    那么布隆过滤器这个说法出自哪里呢? (大家一定很好奇对不对!)

    当然是xx机构~~此处保护自己的狗头~~记住,他们为了割韭菜,一定会选择一些看起来极为高端,但是落地巨不靠谱的方案(这也是区分一个机构到底是割韭菜还是真正有水平的标杆,小白不懂,很容易被坑)~~看到这里,真是惭愧,我的第一篇文章也是写这个方案了,但是在落地过程中,发现了不对劲(此处省略一万字的检讨文,烟哥垃圾~~)。

    (2)布谷过滤器

    那么,为了解决布隆过滤器查询性能弱、空间利用效率低、不支持反向操作等问题,又有一篇文章诞生了,主张用布谷过滤器来解决缓存击穿问题!

    但是,神奇的事情来了,基本上所有的文章都在说布谷过滤器多么多么牛逼,却没有任何落地的方案~

    记住,我们平时写代码,一定是怎么方便怎么来!再记住,面试是一回事,代码落地是另一回事~

    那,真正简便的方案是什么样的呢?来,我们一步步来~

    真正方案

    假设,你此刻用的是springboot-2.x的版本,你为了能够连接redis,你在pom文件里加入如下依赖

    <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-Redis</artifactId></dependency>

    然后呢,我们修改application.yml

    spring:  datasource:    ...  redis:    database: ...    host: ...    port: ...(省事,不全贴了)

    ok,说到这里,就不得不说一下spring-cache了,Spring3.1之后,引入了注解缓存技术,其本质上不是一个具体的缓存实现方案,而是一个对缓存使用的抽象,通过在既有代码中添加少量自定义的各种annotation,即能够达到使用缓存对象和缓存方法的返回对象的效果。Spring的缓存技术具备相当的灵活性,不仅能够使用SpEL(Spring Expression Language)来定义缓存的key和各种condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存集成。

    例如:我们在代码中经常有这么一段逻辑,在目标方法执行前,会根据key先去缓存中查询看是否有数据,有就直接返回缓存中的key对应的value值,不再执行目标方法;没有则执行目标方法,去数据库查询出对应的value,并以键值对的形式存入缓存。

    如果我们不使用例如spring-cache的注解框架,你的代码中会充斥着大量冗余代码,而用了该框架后,以@Cacheable注解为例, 该注解在方法上,表示该方法的返回结果是可以缓存的。

    也就是说,该方法的返回结果会放在缓存中,以便于以后使用相同的参数调用该方法时,会返回缓存中的值,而不会实际执行该方法。

    那么,你的代码只需要这么写

    @Override@Cacheable("menu")public Menu findById(String id) {    Menu menu = this.getById(id);    if (menu != null){        System.out.println("menu.name = " + menu.getName());    }    return menu;}

    在这个例子中,findById 方法与一个名为 menu 的缓存关联起来了。调用该方法时,会检查 menu 缓存,如果缓存中有结果,就不会去执行方法了。

    ok,说到这里,其实都是大家懂得东西!!接下来开始我们的主题:如何解决缓存击穿问题!顺便讲讲穿透和雪崩问题!

    来来来,我们回忆一下缓存击穿,穿透以及缓存雪崩的概念!

    缓存穿透

    高并发下,查询一个不存在的值时,缓存不会被命中,导致大量请求直接落到数据库上,如活动系统里面查询一个不存在的活动。 多嘴一句:缓存穿透是指,请求的是缓存和数据库中都没有的数据!

    对于缓存穿透问题,有一个很简单的解决方案,就是缓存NULL值~从缓存取不到的数据,在数据库中也没有取到,直接返回空值。

    那么spring-cache中,有一个配置是这样的

    spring.cache.redis.cache-null-values=true

    带上该配置后,就可以缓存null值了,值得一提的是,这个缓存时间要设的少一点,例如15秒就够,如果设置过长,会导致正常的缓存也无法使用。

    缓存击穿

    在高并发下,对一个特定的值进行查询,但是这个时候缓存正好过期了,缓存没有命中,导致大量请求直接落到数据库上,如活动系统里面查询活动信息,但是在活动进行过程中活动缓存突然过期了。 多嘴一句:缓存击穿是指,请求的是缓存没有,而数据库中有的数据!

    记住,解决击穿的最简单的方法,只有一个,就是限流!至于怎么限,其实可以各显神通!例如其他文章提到的布隆过滤器,布谷过滤器等,不过是限流方式之一而已!甚至,你用一些其他的限流组件也是可以的!

    这里就要说spring-cahce的另一个配置了!

    在缓存过期之后,如果多个线程同时请求对某个数据的访问,会同时去到数据库,导致数据库瞬间负荷增高。Spring4.3为@Cacheable注解提供了一个新的参数“sync”(boolean类型,缺省为false),当设置它为true时,只有一个线程的请求会去到数据库,其他线程都会等待直到缓存可用。这个设置可以减少对数据库的瞬间并发访问。

    看到这里!!这不就是一个限流方案么?

    所以解决方法就是,加一个属性sync=true,就行。代码就像下面这样

    @Cacheable(cacheNames="menu", sync="true")

    用了该属性后,可以指示底层将缓存住,使只有一个线程可以进入计算,而其他线程堵塞,直到返回结果更新到缓存中。

    当然,看到这里,一定会有人和我抬杠!他的问题是这样的!

    你这个只是针对单机的限流,并不是整体集群的限流!也就是说,假设你的集群搭建了3000个pod,最差的情况下就是,3000个pod上,每个pod都会发起一个请求去数据库查询,照样还是会导致数据库连接数不够用,等等资源问题!

    对于这个问题我只能说!少年,但凡你的公司产品达到这种流量规模,此刻你就不会在看我的文章!你此刻关心的问题是:

    (1)哎,买深圳湾一号还是深圳湾公馆呢,纠结!
    (2)昨天美股又跌了,又损失了两套房
    (3)昨天提前撤单了,又少挣了几万
    ....(省略一万字)

    当然,如果你非要解决,也有办法。spring的aop有套路的,比如@Transactional的Advice是TransactionInterceptor,那么cache也对应对一个CacheInterceptor,我们只要去改CacheInterceptor,这个切面就能解决。在里头做一个分布式锁!伪代码如下

    flag := 取分布式锁if flag {    走数据库查询,并缓存结果}{    睡眠一段时间,再次尝试获取key的值}

    但是,我还是要多嘴提一句,真没必要~~ 记住一句话,立足实际出发~但凡你的业务到了那种级别,是可以做到区域部署的,完全可以规避开这类问题。

    缓存雪崩

    在高并发下,大量的缓存key在同一时间失效,导致大量的请求落到数据库上,如活动系统里面同时进行着非常多的活动,但是在某个时间点所有的活动缓存全部过期。

    那么针对该问题,最简单的解决方法就是,过期时间加随机值!

    但是很麻烦的是,我们在使用@Cacheable注解的时候,原生功能没法直接设置随机过期时间的。

    这个老实说,真没啥好方法,只能自己继承RedisCache,对其增强,改写其中的put方法,带上随机时间!

    “怎么使用spring-cache代码解决缓存击穿问题”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    --结束END--

    本文标题: 怎么使用spring-cache代码解决缓存击穿问题

    本文链接: https://lsjlt.com/news/327975.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • 怎么使用spring-cache代码解决缓存击穿问题
      本篇内容介绍了“怎么使用spring-cache代码解决缓存击穿问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!正文目前缺陷首先,为什么说...
      99+
      2023-06-30
    • 使用spring-cache一行代码解决缓存击穿问题
      目录引言正文目前缺陷真正方案缓存穿透缓存击穿缓存雪崩文末引言 今天,重新回顾一下缓存击穿这个问题! 之所以写这个文章呢,因为目前网上流传的文章落地性太差(什么布隆过滤器啊,布谷过滤器...
      99+
      2024-04-02
    • Spring Cache怎么使用Redisson分布式锁解决缓存击穿问题
      本篇内容主要讲解“Spring Cache怎么使用Redisson分布式锁解决缓存击穿问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring Cache怎么使用Red...
      99+
      2023-06-30
    • Redis缓存击穿和穿透问题怎么解决
      Redis缓存击穿和穿透是常见的性能问题,可以通过以下方法来解决: 缓存击穿:当某个热点数据失效时,大量请求同时访问数据库,导致...
      99+
      2024-05-07
      Redis
    • 怎么解决Redis缓存雪崩、击穿与穿透问题
      这篇文章主要讲解了“怎么解决Redis缓存雪崩、击穿与穿透问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么解决Redis缓存雪崩、击穿与穿透问题”吧!...
      99+
      2022-11-30
      redis
    • 如何解决redis缓存穿透、缓存击穿、缓存雪崩的问题
      这篇文章主要介绍了如何解决redis缓存穿透、缓存击穿、缓存雪崩的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。缓存穿透:key中对应的...
      99+
      2024-04-02
    • redis缓存击穿怎么解决
      redis缓存击穿的解决方案:加互斥锁:在查询数据库之前获取分布式锁,防止并发查询。异步更新缓存:将缓存更新操作放入队列中异步执行,避免并发更新。热点数据永不过期:设置热点数据较长的过期...
      99+
      2024-06-25
      redis
    • 详解SpringCache使用Redisson分布式锁解决缓存击穿问题
      目录1 什么是缓存击穿2 为什么要使用分布式锁3 什么是Redisson4 Spring Boot集成Redisson4.1 添加maven依赖4.2 配置yml4.3 配置Redi...
      99+
      2024-04-02
    • Redis中缓存穿透/击穿/雪崩问题和解决方法
      目录缓存问题1. 缓存穿透---查不到解决方案2. 缓存击穿---量太大,缓存过期解决方案3. 缓存雪崩解决方案缓存问题 1. 缓存穿透---查不到 缓存穿透是指用户想查询一个数据,...
      99+
      2024-04-02
    • 缓存穿透、缓存击穿、缓存雪崩、热点数据失效问题的解决方案
      在我们的平常项目中多多少少会用到缓存,因为一些数据没必要每次查询都跑到数据库中查询。 1、缓存穿透         请求去查询一条不存在的数据,也就是缓存和数据库都查询不到这条数据,但每次请求都会打到数据库上去。        ...
      99+
      2021-10-17
      缓存穿透 缓存击穿 缓存雪崩 热点数据失效问题的解决方案
    • 怎么在java中解决缓存穿透问题
      怎么在java中解决缓存穿透问题?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Java有哪些集合类Java中的集合主要分为四类:1、List列表:有序的,可重复的;2、Qu...
      99+
      2023-06-14
    • 关于缓存穿透,缓存击穿,缓存雪崩,热点数据失效问题的解决方案(转)
      1.我们使用缓存时的业务流程大概为: 当我们查询一条数据时,先去查询缓存,如果缓存有就直接返回,如果没有就去查询数据库,然后返回。这种情况下就可能出现下面的一些现象。 2.缓存穿透 2.1什么是缓存穿透 缓存穿透是指查询一个一定不存在的数...
      99+
      2017-06-16
      关于缓存穿透,缓存击穿,缓存雪崩,热点数据失效问题的解决方案(转)
    • redis击穿、雪崩和穿透问题怎么解决
      这篇文章主要讲解了“redis击穿、雪崩和穿透问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“redis击穿、雪崩和穿透问题怎么解决”吧!Redis击穿redis缓存击穿是指某一个...
      99+
      2023-06-29
    • 怎么使用Spring三级缓存解决循环依赖问题
      这篇文章主要介绍了怎么使用Spring三级缓存解决循环依赖问题的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用Spring三级缓存解决循环依赖问题文章都会有所收获,下面我们一起来看看吧。循环依赖什么是循环...
      99+
      2023-07-05
    • Gradle Build Cache引发的Task缓存编译问题怎么解决
      今天小编给大家分享一下Gradle Build Cache引发的Task缓存编译问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有...
      99+
      2023-07-02
    • Java代码读取文件缓存问题解决
      一、业务场景 最近遇到了一个Java文件读取的缓存问题,打远程断点出现的也是原来的老代码参数,好在晚上十点突然找到了解决方案,豁然开朗,现整理分享思路,希望对遇到同样文件读取缓存问题...
      99+
      2024-04-02
    • Redis缓存问题怎么解决
      这篇文章主要讲解了“Redis缓存问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Redis缓存问题怎么解决”吧!LevelDB 来了!它是 Go...
      99+
      2024-04-02
    • vue缓存问题怎么解决
      Vue缓存问题可以通过以下几种方式来解决:1. 使用路由的meta信息:在路由配置中,可以设置meta信息,包括是否需要缓存组件等。...
      99+
      2023-05-23
      vue缓存问题 vue
    • Spring使用三级缓存解决循环依赖的问题
      Spring如何使用三级缓存解决循环依赖在没开始文章之前首先来了解一下什么是循环依赖 @Component public class A { @Autowired ...
      99+
      2024-04-02
    • Application Cache未缓存文件无法访问怎么解决
      这篇文章主要讲解了“Application Cache未缓存文件无法访问怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Application Cac...
      99+
      2024-04-02
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作