缓存击穿?这么做就对了!

1,037 阅读3分钟

前言

作为后端开发工程师,不管是在工作中,还是面试交谈中,只要涉及到Redis,或者缓存的问题,绝对必不开的问题,那就是缓存穿透了。这篇文章主要讲解为什么会出现缓存击穿。本文的缓存以Redis为例,其余的中间价,解决方案的思想一样,个别Api可能不一致。

产生原因

首先缓存击穿的情况呢,一定是Redis当作缓存使用,而不是当数据库使用,如果当数据库使用的话,是没有这样的问题存在的。

这里以掘金的一个抽奖例子为例吧。

image.png 假设一下,围观大奖这一块的数据,为了减少数据库压力,可以不可以放到缓存中。如果用户请求,通过缓存拿到列表返回这个数据。

image.png

那么这个时候会有一个问题,既然是缓存,他肯定是有一个过期时间的。那么在这个时候,恰巧就那么巧有大量的流量来请求这个接口,那这个时候缓存都没有了,那最后还是会去请求数据库去获取数据,那么称这个现象呢,就叫缓存穿透。

解决办法

那这个时候会有人想,既然问题的产生原因是过期时间。那不给他过期时间是不是就可以了。如果是这个情况是在业务中产生的话,那确实可以了。
但是会产生一个问题,后台数据如果更新了,怎么去更新redis中的缓存。还有就是,如果这个缓存特别大,那是不是占用了特别大的Redis空间呢,这个方法不可取。

那么具体怎么做呢?先来看一张图

image.png

这个业务的大概的逻辑是这样的。我们仅需要对这个部分的业务代码进行一点改动。

image.png 在上图贴出了要改动的点,具体讲解一下.

  1. 第一步 还是从redis中获取数据
  2. 第二步 如果redis中拿到的是null,这里做了个操作,setnx(lock, true)
    • 首先要说一下setnx是什么意思,全称(set if not exists)看字面意思可以看出来,不存在的时候插入。
    • 这里的加这句话的意思呢,就是表明,已经有人去查寻数据库了,后面的就不要查了,你在那里等着就行。我查到了会重新塞回去的。
  3. 第三步 查询数据库,放入缓存,把锁设置取消,然后返回前端。

话题延伸

这里留一个互动的小思考题,就是我上方的文章中有提到过的,如果数据库有更新,怎么做可以把缓存也更新,保证一致性。

有好的方案欢迎在评论区交流,这篇文章比较简单,就先这样了。

都看到这了,不点个赞再走吗🤪