解决redis缓存击穿问题之布隆过滤器

news2024/11/15 17:45:01

布隆过滤器

1. 什么是布隆过滤器

布隆过滤器(Bloom Filter)是一个空间效率很高的数据结构,用于判断一个元素是否在一个集合中。布隆过滤器的核心思想是利用位数组和一系列随机映射函数(哈希函数)来快速判断某个元素是否存在于集合中,但存在一定的误判率。

2. 参数

布隆过滤器的参数主要包括以下几个方面:

(1)预插入元素大小 (n) :预计加入到布隆过滤器中的元素总数

(2)误判率 (p):将不存在的元素误判为存在的概率。在数据量大小一致的情况下,位数组长度越长误判率越小

(3)哈希函数个数 (k) :布隆过滤器使用的哈希函数数量,将输入数据映射到位数组的一个或多个位置上

(4)位数组大小 (m) :表示状态的二进制位的数量

  • k和m都可根据n和p计算得出,所以初始化布隆过滤器时只需要给出n和p的大小即可

  • 布隆过滤器在线计算网址:https://krisives.github.io/bloom-calculator/

3. 布隆过滤器的原理

(1)建立一个二进制向量,并将所有位设置为0

(2)选定K个散列函数,用于对元素进行K次散列,计算向量的位下标

(3)添加元素:当需要添加一个元素到布隆过滤器中时,首先使用多个哈希函数对该元素进行哈希运算,得到多个哈希值。然后,将这些哈希值对应的位数组中的位置设置为1。

(4)查询元素(不存在一定不存在,存在不一定存在):同样使用多个哈希函数对该元素进行哈希运算,然后检查所有哈希值对应的位数组中的位置是否都为1。如果所有位置都为1,则认为该元素可能存在于集合中(注意是“可能”,因为存在误判的可能性);如果有任何一个位置为0,则确定该元素一定不存在于集合中。

假设有元素x,y,z三个元素加入数组中,且哈希函数的个数为3。如上图所示,每个元素根据hash函数计算可得3个哈希值。现有一个w元素对应的哈希值分别为4、13和15,查询元素需要判断三个位置的值都为1。图中下标15的位置为0,所以该元素不存在。

如果再添加一个元素m,且m的哈希值其中有一个为15。这时4、13和15三个位置都为1,就会判断w元素存在,这种误判是由哈希冲突导致的。

如何解决布隆过滤器的误判?(不能完全解决,只能降低概率)

  • 增加哈希函数的数量,降低哈希碰撞的概率

  • 增大数组长度,也可以降低哈希碰撞的概率

4. 布隆过滤器的优缺点

  • 优点

  • 占用空间小:相对于直接存储元素,布隆过滤器使用的空间要小得多。

  • 查询速度快:布隆过滤器的查询操作通常只需要进行少量的位运算和哈希计算,因此速度非常快。

  • 缺点

  • 存在一定的误判率:由于哈希冲突和位数组大小的限制,布隆过滤器无法保证查询结果的绝对准确性。

  • 无法删除元素:布隆过滤器不支持删除操作,因为删除操作会影响其他元素的判断结果。布隆过滤器的使用场景布隆过滤器用于判断一个元素是否可能在一个集合中,可以用于很多场景。

5. 布隆过滤器的使用场景

布隆过滤器用于判断一个元素是否可能在一个集合中,可以用于很多场景。

  • 解决Redis缓存穿透问题

  • 垃圾邮件过滤

  • 用户请求限流,快速判断用户或IP地址的请求频率是否超过了限制

  • 解决新闻推荐过的不再推荐(类似抖音刷过的往下滑动不再刷到)SpringBoot中实现布隆过滤器

6. SpringBoot中实现布隆过滤器解决缓存穿透

(1)引入依赖

Redisson 是一个高性能的 Java 客户端库,用于开发基于 Redis 的分布式应用程序。

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

XML

(2)布隆过滤器配置

  • 在application.properties中配置好redis的信息,将其注入到ReidsConfig类的属性中,根据属性配置redis的连接客服端

@Value("${spring.redis.host}")String host;@Value("${spring.redis.port}")String port;@Value("${spring.redis.password}")String password;
@Beanpublic RedissonClient redisson(){    Config config = new Config();    config.useSingleServer()    .setAddress("redis://"+host+":"+port)    .setPassword(password);    return Redisson.create(config);}

Java

(3)在商品业务中添加布隆过滤器

@Service
@Slf4j
public class ProductService {
    @Autowired
    ProductDao productDao;
    @Resource
    RedisTemplate<String,Product> redisTemplate;
    @Autowired
    RedissonClient redissonClient;
    RBloomFilter<Integer> productFilter;

    /**
     * 初始化商品数据,将商品数据读入到redis的productFilter中
     */
    @PostConstruct  //项目启动时执行,也可以定时执行,比如每天执行一次
    public void init(){
        // 查询商品列表(只需要查询商品id列表,速度更快)
        List<Product> productList = productDao.selectProductAll();
        productFilter = redissonClient.getBloomFilter("productFilter");
        // 初始化布隆过滤器,设置预计元素个数(结合每天的业务量设置)和误判率
        productFilter.tryInit(productList.size() * 2L,0.01);
        // 添加商品到布隆过滤器中
        productList.forEach(product -> productFilter.add(product.getId()));
    }

    /**
     * 根据id查询商品信息
     */
    public Product getProductById(Integer id){
        String productIdKey = "product."+id;

        // 判断商品是否在布隆过滤器中存在
        if(!productFilter.contains(id)){
            throw new RuntimeException("布隆过滤器不存在该商品");
        }

        // 商品可能存在,在redis中查询商品信息
        Product product = redisTemplate.opsForValue().get(productIdKey);
        if(product!=null){
            log.debug("在redis中查询到商品信息");
            return product;
        }

        // redis中没有,在数据库中查询商品信息
        product = productDao.selectProductById(id);
        if(product==null){
            // 在RBloomFilter工具类中没有找到移除元素的方法,所以这里直接抛出了异常
            throw new RuntimeException("数据库中不存在该商品");
        }

        log.debug("在数据库中有,现存入redis中");
        redisTemplate.opsForValue().set(productIdKey,product);

        return product;
    }

    /**
     * 添加商品,并添加到布隆过滤器中
     */
    public Integer addProduct(Product product){
 
        int affect = productDao.insertProduct(product);

        productFilter.add(product.getId());

        return affect;
    }}

Java

7. 思考

思考一: 如果商品id是有序的且从0开始,使用哪种方式记录表中的所有id比较好? 哪个空间更小?

(1)简单的位图,即商品id作为偏移量,将对应的位置设为1

(2)布隆过滤器,设置误判率为0.01

商品ID是从0开始的连续整数,那么使用位图是更好的选择。位图不仅空间效率更高,而且没有误报的问题。(如果不保证误判率,布隆过滤器空间效率更高)

注意: 使用简单位图的方式时,内存占用由最大的id决定,需要保证id不会大幅度跳动

思考二: 后续数据库中的数据量超过了设置的预添加元素数,布隆过滤器的数组会自动扩容吗?

不会。布隆过滤器一旦初始化,其位数组的大小和哈希函数的数量就是固定的。这意味着它不能自动扩容来适应更多的元素。如果尝试插入的元素数量超过了布隆过滤器的设计容量,误判率将会上升。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2150540.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringBoot+Vue+MySQL的网上租赁系统

系统展示 用户前台界面 管理员后台界面 系统背景 在当前共享经济蓬勃发展的背景下&#xff0c;网上租赁系统作为连接租赁双方的重要平台&#xff0c;正逐步改变着人们的消费观念和生活方式。通过构建一个基于SpringBoot、Vue.js与MySQL的网上租赁系统&#xff0c;我们旨在为用户…

LangChain 和 Elasticsearch 加速构建 AI 检索代理

作者&#xff1a;来自 Elastic Joe McElroy, Aditya Tripathi, Serena Chou Elastic 和 LangChain 很高兴地宣布发布新的 LangGraph 检索代理模板&#xff0c;旨在简化需要代理使用 Elasticsearch 进行代理检索的生成式人工智能 (GenAI) 代理应用程序的开发。此模板预先配置为使…

基于机器学习的癌症数据分析与预测系统实现,有三种算法,bootstrap前端+flask

研究背景 癌症作为全球范围内最主要的死亡原因之一&#xff0c;已成为当代医学研究和公共健康的重大挑战。据世界卫生组织&#xff08;WHO&#xff09;的统计&#xff0c;癌症每年导致全球数百万人的死亡。随着人口老龄化、环境污染和生活方式的改变&#xff0c;癌症的发病率逐…

Pytorch学习---基于经典网络架构ResNet训练花卉图像分类模型

基于经典网络架构训练图像分类模型 导包 import copy import json import time import torch from torch import nn import torch.optim as optim import torchvision import os from torchvision import transforms, models, datasets import numpy as np import matplotlib.…

【使用Hey对vllm接口压测】模型并发能力

使用Hey对vllm进行模型并发压测 docker run --rm --networkknowledge_network \registry.cn-shanghai.aliyuncs.com/zhph-server/hey:latest \-n 200 -c 200 -m POST -H "Content-Type: application/json" \-H "Authorization: xxx" \-d {"model"…

【类型黑市】指针

大家好我是#Y清墨&#xff0c;今天我要介绍的是指针。 意义 指针就是存放内存地址的变量。 分类 因为变量本身是分类型的&#xff0c;我们学过的变量类型有 int, long long, char, double, string, 甚至还有结构体变量。 同样&#xff0c;指针也分类型&#xff0c;如果指针指向…

云韧性,现代云服务不可或缺的组成部分

韧性&#xff0c;一个物理学概念&#xff0c;表示材料在变形或者破裂过程中吸收能量的能力。韧性越好&#xff0c;则发生脆性断裂的可能性越小。 如今&#xff0c;韧性也延伸到企业特质、产品特征等之中&#xff0c;用于形容企业、产品乃至服务的优劣。同样&#xff0c;随着云…

3. Internet 协议的安全性

3. Internet 协议的安全性 (1) 常用网络协议的功能、使用的端口及安全性 HTTP协议 功能:用于从服务器传输超文本到本地浏览器。端口:默认是80端口。安全性:不提供数据加密,存在数据泄露和中间人攻击风险。使用HTTPS协议(443端口)可以增强安全性。FTP协议 功能:实现文件的…

电脑录课软件哪个好用,提高教学效率?电脑微课录屏软件推荐

在当今这个数字化时代&#xff0c;教育领域也迎来了翻天覆地的变化。随着远程教学和在线学习的普及&#xff0c;教师们开始寻求更高效、更便捷的教学工具来提升教学质量和学生的学习体验。电脑录课软件&#xff0c;作为现代教育技术的重要组成部分&#xff0c;能够帮助教师轻松…

【CPP】类与继承

14 类与继承 在前面我们提到过继承的一些概念,现在我们来回顾一下 打个比方:在CS2中我们把玩家定义为一个类 class 玩家: 血量:100阵营(未分配)服饰(未分配)位置(未分配)武器(未分配)是否允许携带C4(未分配)是否拥有C4(未分配) 当对局创建时,会新生成两个类,这两个类继承自&qu…

【Linux庖丁解牛】—Linux基本指令(上)!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a; Linux庖丁解牛 &#x1f516;克心守己&#xff0c;律己则安 目录 1、 pwd命令 2、ls 指令 3、cd 指令 4、Linux下的根目录 5、touch指令 6、 stat指令 7、mkdi…

LabVIEW提高开发效率技巧----采用并行任务提高性能

在复杂的LabVIEW开发项目中&#xff0c;合理利用并行任务可以显著提高系统的整体性能和响应速度。并行编程是一种强大的技术手段&#xff0c;尤其适用于实时控制、数据采集以及多任务处理等场景。LabVIEW的数据流编程模型天然支持并行任务的执行&#xff0c;结合多核处理器的硬…

OrCAD使用,快捷键,全选更改封装,导出PCB网表

1 模块名称 2 快捷键使用 H: 镜像水平 V&#xff1a;镜像垂直 R: 旋转 I: 放大 O&#xff1a; 放小 P&#xff1a;放置元器件 W&#xff1a; 步线 B&#xff1a; 总线&#xff08;无电气属性&#xff09; E: 总线连接符&#xff08;和BUS一起用&#xff09…

【网络通信基础与实践第四讲】用户数据报协议UDP和传输控制协议TCP

一、UDP的主要特点 1、UDP是无连接的&#xff0c;减少了开销和发送数据之前的时延 2、UDP使用尽最大努力交付&#xff0c;但是不保证可靠交付 3、UDP是面向报文的。从应用层到运输层再到IP层都只是添加一个相应的首部即可 4、UDP没有拥塞机制&#xff0c;源主机以恒定的速率…

基于JAVA+SpringBoot+Vue的学生干部管理系统

基于JAVASpringBootVue的学生干部管理系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#x1f345; 哈…

力扣题解2376

大家好&#xff0c;欢迎来到无限大的频道。 今日继续给大家带来力扣题解。 题目描述&#xff08;困难&#xff09;&#xff1a; 统计特殊整数 如果一个正整数每一个数位都是 互不相同 的&#xff0c;我们称它是 特殊整数 。 给你一个 正 整数 n &#xff0c;请你返回区间 …

【Python报错已解决】SyntaxError invalid syntax

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

锐尔15注册机 锐尔文档扫描影像处理系统15功能介绍

锐尔文档扫描影像处理系统是一款全中文操作界面的文件、档案扫描及影像优化处理软件&#xff0c;是目前国内档案数字化行业里专业且优秀的影像优化处理软件。 无论是从纸质文件制作高质量的影像文件&#xff0c;或是检查已经制作好的影像文件&#xff0c;锐尔文档扫描影像处理…

Generative Models from the perspective of Continual Learning【小白读论文】

摘要&#xff1a; 本文在持续学习情况下评估各种生成模型。 本文研究了几种模型如何学习和遗忘&#xff0c;并考虑了各种持续学习策略&#xff1a;回放、正则化、生成重放和微调。 我们使用两个定量指标来估计生成质量和记忆能力。 我们在三个常用的持续学习基准&#xff08;MN…

RabbitMQ08_保证消息可靠性

保证消息可靠性 一、生产者可靠性1、生产者重连机制&#xff08;防止网络波动&#xff09;2、生产者确认机制Publisher Return 确认机制Publisher Confirm 确认机制 二、MQ 可靠性1、数据持久化交换机、队列持久化消息持久化 2、Lazy Queue 惰性队列 三、消费者可靠性1、消费者…