当前位置: 首页 > article >正文

【Redis实战篇】利用布隆过滤器解决缓存穿透问题

前言

在日常业务中,我们将数据存放在数据库中,查询时从数据库查询,但是这样效率并不高,为了提高查询效率,我们将数据缓存在Redis中,查询时直接从Redis中查询,由于Redis中的数据是存放在内存中的,所以查询的效率得到大大提升。但从而也会带来一些问题,其中缓存穿透就是其中一个问题。

文章目录

  • 什么是缓存穿透?
  • 解决方案
    • 1.将DB所有数据放入缓存中
    • 2.布隆过滤器
      • 什么是布隆过滤器
      • 布隆过滤器的误判
  • 实际应用
    • 1.引入依赖
      • 1.1引入Redisson依赖
      • 1.2 配置Redis参数
    • 2.创建布隆过滤器实例
    • 3.在代码中使用
    • 4. 应用中存在问题

什么是缓存穿透?

查询一个不存在的数据,mysql查不到数据也会直接写入缓存,就会导致每次请求都查询数据库

在这里插入图片描述

海量用户如果说查询的用户名存在或不存在,全部请求数据库,会将数据库直接打满。

解决方案

1.将DB所有数据放入缓存中

将数据库所有的数据放入缓存中。

存入缓存引出的问题
这里的数据都是永久数据。占用Reids内存太高。所以不采取这个方案。

2.布隆过滤器

下面为流程图
在这里插入图片描述

什么是布隆过滤器

位图

所谓位图,就是用每一位来存放某种状态,适用于海量数据,整数,数据无重复的场景。通常是用来判断某个数据存不存在的。

布隆过滤器概念

布隆过滤器是由布隆(Burton Howard Bloom)在1970年提出的 一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间
在这里插入图片描述
布隆过滤器的思想是将一个元素用多个哈希函数映射到一个位图中,因此被映射到的位置的比特位一定为1
所以可以按照以下方式进行查找:分别计算每个哈希值对应的比特位置存储的是否为零,只要有一个为零,代表该元素一定不在哈希表中,否则可能在哈希表中。
注意:布隆过滤器如果说某个元素不存在时,该元素一定不存在,如果该元素存在时,该元素可能存在,因
为有些哈希函数存在一定的误判

优点: 内存占用少、没有多余key
缺点: 实现复杂,存在误判

布隆过滤器的误判

首先布隆过滤器的误判是可以调整的。

  • 布隆过滤器要设置初始容量。容量设置越大,冲突几率越低。
  • 布隆过滤器会设置预期的误判值。

其次在使用布隆过滤器时,就需要考虑误判是不是可以接受

例如在用户设置用户名时,“aaaa”在数据库中不存在,但是在布隆过滤器中的结果返回是存在的,那么“aaaa”这个用户名就不能再被注册,这对用户并不会造成实质性的损失,所以这个误判就是可以接受的。

而在有金钱交易的业务场景中,误判就是不能被接受的。

实际应用

1.引入依赖

1.1引入Redisson依赖

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

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
</dependency>

1.2 配置Redis参数

这个参数因人而异,根据自己的host地址以及密码等配置即可。

2.创建布隆过滤器实例

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 布隆过滤器配置
 */
@Configuration
public class RBloomFilterConfiguration {

    
    @Bean
    public RBloomFilter<String> CachePenetrationBloomFilter(RedissonClient redissonClient) {
        RBloomFilter<String> cachePenetrationBloomFilter = redissonClient.getBloomFilter("xxx");
        cachePenetrationBloomFilter.tryInit(0, 0);
        return cachePenetrationBloomFilter;
    }
}

这里tryInit有两个核心参数

public boolean tryInit(long expectedInsertions, double falseProbability)
  1. expectedInsertions:预估布隆过滤器存储的元素长度
  2. falseProbability:运行的误判率

误判率越低,位数组越长,布隆过滤器占用内存越大;
误判率越低,散列Hash函数越多,计算耗时越长。

3.在代码中使用

private final RBloomFilter<String> userRegisterCachePenetrationBloomFilter;

4. 应用中存在问题

当布隆过滤器中不存在时,代表数据要插入数据库,如果恶意短时间内(毫秒级)发送海量请求,这些请求都要落到数据库,造成数据库压力,此时就要引入分布式锁来解决问题,锁定当前数据进行串行执行,防止恶意请求将数据打到数据库。

 RLock lock = redissonClient.getLock(...);
       try {
           if (lock.tryLock()){
               int insert = baseMapper.insert(...);
               if (insert < 1){
                   throw new ClientException(...);
               }
               userRegisterCachePenetrationBloomFilter.add(...);
               return;
           }
           throw new ClientException(...);
       }finally {
           lock.unlock();
       }


http://www.kler.cn/a/394565.html

相关文章:

  • 【项目组件】第三方库——websocketpp
  • 统信UOS开发接口DTK
  • Javaweb—Ajax与jQuery请求
  • 实现 MVC 模式
  • 计算机网络(3)网络拓扑和IP地址,MAC地址,端口地址详解
  • (干货)Jenkins使用kubernetes插件连接k8s的认证方式
  • 力扣题目解析--合并两个链表
  • SystemVerilog学习笔记(十一):接口
  • 相机光学(四十)——2x2 Adjacent Pixel Binning
  • 小程序开发者工具的network选项卡中有某域名的接口请求,但是在charles中抓不到该接口
  • Python图像识别详解
  • STL学习-排序算法
  • Python-requests模块详解!
  • 威联通Docker Compose搭建NAS媒体库资源工具NAS Tools
  • C++单例模式实现
  • CSS盒子的定位> (中篇)#绝对定位#附练习
  • JAVA开源项目 微服务在线教育系统 计算机毕业设计
  • 【Linux上部署Dify】从本地到云端:在Linux上部署Dify并实现公网访问的流程
  • Go语言进阶之Context控制并发
  • STM32F1学习——I2C通信
  • 第5章: 图像变换与仿射操作
  • vue3+vite+js env引入
  • 湾区聚力 开源启智 | 2024 CCF中国开源大会暨第五届OpenI/O启智开发者大会闪耀深圳
  • Scroll 生态全面启动为 Pencils Protocol 赋能,DAPP 将迎强势腾飞
  • 【MySQL】SQL语言
  • android studio new flutter project-运行第一个flutter项目