记一次redis缓存击穿问题

前言:

首先先介绍下项目环境:SpringBoot+Redis+JPA等。之所以写这篇文章是为了总结下线上的一个击穿问题,以便于对redis有更为深刻的认识和理解。

这里我就不使用项目中的代码了,使用自己的测试代码来说明主要问题。

一、业务场景:

使用redis的理由是在用户访问量很大的时候,如果一次次去从数据库中读取数据,无疑会增加数据库的负担(重要的数据当然还是要从库中读),但对于诸如用户浏览记录或者xxx列表之类的数据,数据量是巨大的,如果从库中读显然不可行,所以考虑存到redis中,大致的流程是这样,注意:此图和实际业务无关只是为了说明问题

好了接下来来看下代码,由于使用的是springboot因此在整合redis的时候使用了redisTemplete

嗯,看上去没有什么问题,来测试一下,为了模拟环境,我们使用25条线程执行10万条请求,来看是否像我们的预想结果即:如果是第一次查询的话,默认去查数据库,由于之后将信息放到了缓存,因此第二次应该查缓存。

为了验证次问题我将之前在redis中存的数据全部移除,然后我们来执行一下测试程序:

结果:

我们再来看一下redis客户端中有没有缓存到数据,可以看到缓存了数据,说明逻辑是对的。

但是,我们可以看到结果并没有向我们想象的那样第一次查数据库,而是有部分数据都是从数据库中读取的,后面才开始查缓存的,如果并发再大点的话,查数据库的数量会更多,那么我们该如何避免这种情况呢?

二、如何避免缓存击穿

我们先来分析一下问题出在哪里,10w条查询请求进来,由于是第一次查询所以这个时候redis中是不存在缓存数据的,这个时候因为是并发执行,可能有1000条请求进来,发现redis中没有,于是就去读数据库查了出来,然后将数据设置到了redis中,1001条以后的请求进来后发现redis中已经有了缓存,所以就不去读取数据库而是直接去redis中读取缓存,因此就会出现上面的那种结果。

如何避免呢?我们很容易就想到使用互斥锁,即synchronized它可以保证在某一时刻只有一个对象拥有锁,也就是说当第一条请求进入的时候它拥有了一把锁,那么此时请求流程是怎样的呢?看图~

和之前相同的是所有的请求都可以进入到判断是否为空的逻辑,当判断redis为空后去数据库中查的时候,采用synchronized来锁定当前的对象,也就是用户1的请求,这个时候其他的请求只能等,那么用户1接着就会去数据库中读取,然后把读取到的信息放入到redis中去,当它执行完这一系列流程之后,请求2才开始执行,这时它发现redis中已经有了数据,所以就不去数据库中读取,直接从redis中拿出来显示,所以此时就可以避免缓存击穿的问题,先来看下代码:

可以看到this也就是当前对象被锁定,其他对象就无法继续进入执行,接着我们来清除redis中原有的缓存来测试一下结果:

此时的redis中是没有缓存数据的,接着我们来执行程序:

可以看到此刻虽然redis中没有数据,但是只有第一次从数据库中查询,之后的请求都是从缓存中读取出来,我们再来看下redis缓存中:

备注:当然你也可以将synchronized作用在方法上,这样也可以保证结果的正确性,但是需要注意的是这样的话性能会大大降低,因此当你调用方法的时候其他请求会进行等待,此时方法是阻塞的,而且效率也是低下的,而作用在方法块上的效率显然要比方法上好的多。

原文:https://blog.csdn.net/qq_32967665/article/details/86491095

史上最强Tomcat8性能优化

阿里巴巴为什么能抗住90秒100亿?--服务端高并发分布式架构演进之路

B2B电商平台--ChinaPay银联电子支付功能

学会Zookeeper分布式锁,让面试官对你刮目相看

SpringCloud电商秒杀微服务-Redisson分布式锁方案

查看更多好文,进入公众号--撩我--往期精彩

一只 有深度 有灵魂 的公众号0.0

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值