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

news/2024/10/18 18:28:45/

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

文章目录

  • 【Redis】缓存穿透问题及其解决方案
    • 1. 缓存穿透概念及原因
    • 2. 解决方案
      • 2.1 缓存空对象
        • 2.1.1 缓存空对象的优缺点
        • 2.1.2 改进代码
      • 2.2 布隆过滤
        • 2.2.1 布隆过滤的优缺点

1. 缓存穿透概念及原因

缓存穿透:客户端请求的数据在 缓存数据库 当中都不存在的情况,这样缓存就形同虚设,请求都会直接打到数据库。请求量过大时容易可能造成数据库的宕机。

缓存穿透通常都是人为恶意制造的,因为前端一般不会出现明显bug,但是后端因为对数据的校验不够仔细或者因为数据库本身设计的一些问题,很容易被别人通过测试工具直接请求接口并携带一些特别的参数,这样就会造成了缓存穿透。


2. 解决方案

缓存穿透的常见解决方案有两种:

  1. 缓存空对象
  2. 布隆过滤

我们先设定一个场景:假设这是一个电商平台,我们通过id去查询店铺信息。没处理缓存穿透问题的代码如下:

@Override
public Result queryById(Long id) {//1.从redis查询商铺缓存String key = CACHE_SHOP_KEY + id;String shopJson = stringRedisTemplate.opsForValue().get(key);//2.判断是否存在if (StrUtil.isNotBlank(shopJson)) {//3.存在,直接返回Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}//4.缓存数据不存在,根据id查询数据库Shop shop = getById(id);//5.不存在,返回错误if (shop == null) {return Result.fail("商铺不存在");}stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);return Result.ok(shop);
}

接下来解释两种解决方案及其改进代码。


2.1 缓存空对象

缓存空对象的实现流程如图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9LL41aWf-1673424035601)(C:\Users\zhuhuanjie\AppData\Roaming\Typora\typora-user-images\image-20230111150639152.png)]

解释:当客户端发送请求到达redis时,发现redis中无数据,然后请求继续去查询数据库,发现数据库中也没有数据,那么为防止接下来有很多请求都来查询数据库,所以当数据库查询数据为空时,我们给redis中缓存一个空对象并设置一个过期时间TTL,那么接下来携带和第一次请求相同参数的请求就会直接在redis中获得空对象,然后直接命中返回。


2.1.1 缓存空对象的优缺点

优点:

  • 实现简单,维护方便

缺点:

  • 额外的内存消耗(可能会缓存很多的空对象)
  • 可能造成短期的不一致(缓存空对象的时候数据库没有对应数据,缓存之后数据库就有了对应数据,这样redis和数据库就不一致了,只能等待TTL到期再次查询才能保持一致)

2.1.2 改进代码

改进之后的流程图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ki9lKoV0-1673424035602)(C:\Users\zhuhuanjie\AppData\Roaming\Typora\typora-user-images\image-20230111155354058.png)]

具体代码如下:

@Override
public Result queryById(Long id) {//1.从redis查询商铺缓存String key = CACHE_SHOP_KEY + id;String shopJson = stringRedisTemplate.opsForValue().get(key);//2.判断是否存在if (StrUtil.isNotBlank(shopJson)) {//3.存在,直接返回Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}//此时 shopJson 不是为null就是为""if (shopJson != null) {//为""直接返回错误信息,为null查询数据库return Result.fail("商铺不存在");}//4.缓存数据不存在,根据id查询数据库Shop shop = getById(id);//5.不存在,返回错误if (shop == null) {//缓存空值stringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);return Result.fail("商铺不存在");}stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);return Result.ok(shop);}

仔细比对缓存空对象改进代码和原代码的区别。


2.2 布隆过滤

布隆过滤的实现流程如图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yb1Nq28b-1673424035602)(C:\Users\zhuhuanjie\AppData\Roaming\Typora\typora-user-images\image-20230111151511053.png)]

解释:客户端的请求首先到达布隆过滤器,布隆过滤器存储的结果是数据库中数据hash之后得到的结果,如果布隆过滤器判断请求的数据不存在那么就一定不存在,如果判断存在那么也不一定真的存在(不同数据hash的结果可能相同)。假设判断数据不存在则直接拒绝请求;如果判断数据存在则放行到redis中,redis中有数据则直接返回;redis中无对应数据则再去访问数据库,如果数据库中也没有数据就再次发生了穿透;如果数据库中有数据则直接缓存数据并返回。


2.2.1 布隆过滤的优缺点

优点:

  • 内存占用较少,没有多余key

缺点:

  • 实现复杂
  • 存在误判可能(不同数据的hash结果可能相同)

http://www.ppmy.cn/news/11163.html

相关文章

软件著作权申请注意事项

​软著申请需要哪些材料 ①企业申请:企业营业执照副本复印件(加盖公章)、身份证复印件(正反面)。 个人申请:个人身份证复印件。 ②软件设计/使用说明书文档一份 文档可根据要求提供,可以是软件…

互联网摸鱼日报(2023-01-11)

互联网摸鱼日报(2023-01-11) InfoQ 热门话题 下一个十年,我们需要一款什么样的分析型数据库? VS Code有多么不安全:一个扩展就可能导致公司GitHub中的所有代码被擦除? OpenJDK提议Galahad项目合并GraalV…

Cesium 点击获取/拾取(PICK)的不同用法

Cesium 拾取有多个方法,下面就分别说明一下几种常用方法都是做什么用的,在什么场景下使用。 1. viewer.scene.pick 通过坐标位置,拾取 Entity 、 Primitive、3D-Tiles(Cesium3DTileFeature)对象。 例如获取 Entity …

【VUE2-02】vue2的指令和vue2的缺点

文章目录一、vue条件渲染 v-if二、vue循环渲染 v-for三、vue的事件 v-on四、vue的双向绑定 v-model五、VUE2的缺点5.1 vue底层原理解决方案在上节 【VUE2-01】vue2的起步,中写hello world!例子的时候使用了一个指令 v-bind绑定元素属性一、vue条件渲染 v-if v-if控…

无需离开 Visual Studio 即可编写 Markdown

当您想要格式化代码但又不想牺牲易读性时,Markdown 是一个很好的解决方案。GitHub 将其用于自述文件,我们将其用作 Visual Studio 文档的标准。之前收到了不少来自开发者的反馈,大家希望在 Visual Studio 中使用 Markdown 编辑器。在最近的 V…

CSS知识点大全

目录 CSS Step1.我的第一个CSS程序 Step2.CSS编写的位置 内联样式表 内部样式表 外部样式表

内存函数:学习笔记7

目录 一.前言 二. memcpy模拟实现 三. memmove模拟实现 四.memcmp模拟实现 一.前言 计算机内存的实质就是以字节为编号单元的二进制序列集合,操作内存时我们应具有这样的视角。 二. memcpy模拟实现 库函数memcpy函数首部:void *memcpy( void *dest, …

强(矩阵快速幂)

题目描述 Lh:粉兔你教我一下抽屉原理吧 Clz:就是给你一个长度为 n 的序列,每个数只能取 0,1,2,那你连续取三个数必然有两个相等…… Lh:等等你梭啥,再说一遍 Clz:……emmm 当我没说 Marser&…