Redis缓存击穿问题及解决思路

1. 什么是缓存击穿

缓存击穿也叫热点key问题,就是一个被高并发访问并且缓存重建业务比较复杂的key突然失效了,无数的请求会在一瞬间给数据库带来巨大的冲击。也是缓存雪崩中的一个特例。

2. 解决方案

常见的解决方案有两种:

  • 互斥锁
  • 逻辑过期
    逻辑分析:假设线程1在查询缓存之后,本来应该去查询数据库,然后把这个数据重新加载到缓存的,此时要线程1走完这个逻辑,其他线程就可以从缓存中获取这个数据了,但是线程1在没有走完之前,后续的线程2 3 4 同事来访问这个方法,那么这些线程都不能从缓存中获取数据,那么他们就会同一时间去查缓存,缓存没数据,接着同时去查数据库,同时执行数据库代码,给数据库带来巨大压力。
    在这里插入图片描述

2.1 使用锁来解决(互斥锁)

因为锁能实现互斥性。假设线程过来,只能一个个的来访问数据库,从而避免对数据库访问压力过大,但是这也会影响查询性能,因为此时会让查询的性能从并行编程串行,我们可以采用tryLocak方法+double check来解决这样的问题。
假设现在线程1过来访问,他查询的缓存没有命中,但是此时他获得了锁的资源,那么线程1一个人去执行逻辑,假设线程2过来,线程2在执行过程中,并没有获得锁,那么线程2就可以进行休眠,直到线程1把锁释放后,线程2获得锁,然后再来执行逻辑,此时就能从缓存中拿到数据了。
在这里插入图片描述

2.2 逻辑过期

方案分析:我们之所以会出现这个缓存击穿问题,主要原因是在于我们对key设置了过期时间,假设我们不设置过期时间,其实就不会有缓存击穿的问题,但是不设置过期时间,这样数据不就一直占用我们内存了吗,我们可以采用逻辑过期方案。

我们把过期时间设置在redis的value中,注意:这个过期时间并不会直接作用于redis,而是我们后续通过逻辑代码去处理。假设线程1去查询缓存,然后从value中判断出来当前的数据已经过期了,此时线程1去获得互斥锁,那么其他的线程会进行阻塞,获得了锁的线程他会开启一个线程去进行以前的重构数据的逻辑,直到新开的线程完成这个了逻辑后,才释放锁,而线程1直接进行返回,假设现在线程3过来访问,由于线程2持有着锁,所以线程3无法获得锁,线程3也直接返回数据,只有等到新开的线程2把重建的数据构建完后,其他线程才能走返回正确的数据。

这种方案巧妙在于,异步的构建缓存,缺点在于在构建完缓存之前,返回的都是脏数据。
在这里插入图片描述

2.3 进行对比

互斥锁方案: 由于保证了互斥性,所以数据一致,且实现简单,因此仅仅只需要加一把锁而已,也没有其他的事情需要操心,所以没有额外的内存消耗,缺点在于有锁就会产生死锁,且只能串行执行性能肯定受到影响。

逻辑过期方案: 线程读取过程不需要等待,性能好,有一个额外的线程持有锁去重构数据,但是在重构数据完成之前,其他线程只能返回之前的数据,且实现起来麻烦。
在这里插入图片描述

参考资料:
黑马Redis资料。

若有错误,希望大佬指出。
对你有帮助给点个👍再走呗。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值