布隆过滤器 redis

一.为什么要用到布隆过滤器?

缓存穿透:查询一条不存在的数据,缓存中没有,则每次请求都打到数据库中,导致数据库瞬时请求压力过大,多见于爬虫恶性攻击

因为布隆过滤器是二进制的数组,如果使用了它,可以把需要的对应的全量业务数据的key值全放到布隆过滤器中,内存占用较小,这样就不会击穿数据库

二.数据访问流程

布隆过滤器–>redis缓存–>数据库
1. 布隆过滤器如果不存在,直接返回,不访问缓存和数据库
2. 布隆过滤器有,如果缓存有,直接返回数据
3. 布隆过滤器有,如果缓没有,查数据库

三.原理:

在这里插入图片描述

使用二进制数组,对要存入的key进行多次hash,分配到数组的不同位置,数组的值从0改成1,查询的时候也进行多次hash,命中到数组的位置的值都是1则key可能存在,如果有一个不是1则key一定不存在
在这里插入图片描述

四.缺点

缺点1:

存在误判的情况,比如:hello和你好经过hash后的值一样,出现hash冲突。比如“你好”是存在,“hello”不存在,但他们的hash值一样,就会通过
在这里插入图片描述
解决:

1.根据数据量大小设置误判率。误判率越小,使用的hash函数越多,hash冲突越小,但计算的时间增加,内存占用更多
2.增大布隆过滤器数组

缺点2:

删除困难: 布隆过滤器无法直接删除已添加的元素,因为删除操作会影响其他元素的判断结果。在删除元素时,可能会导致一些位置的位被置为 0,从而影响其他元素的判断结果,增加误判的概率

解决:

只能是重新载入布隆过滤器了。开发定时任务,每隔几个小时,自动创建一个新的布隆过滤器数组替换老的。注意,是几小时,这也就意味着,这一方法在高并发的情况下有巨大缺点

五.代码实践

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.27.2</version>
        </dependency>
import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * redisson客户端使用Bloom过滤器拦截无效请求,解决缓存穿透
 * 项目初始化的时候初始化布隆过滤器(例如把商品编号都放进去),
 * 用户发过来的请求(带商品编号)先经过布隆过滤器过滤,过滤掉的返回null
 *
 */
@Configuration
public class RedissinConfig {


   @Value("${redisson.address}")
   private String addressUrl;


    @Value("${redisson.password}")
    private String password;


    @Bean
    public RedissonClient redissonClient() {
    Config config = new Config();
    config.useSingleServer()
    .setAddress(addressUrl)
    .setRetryInterval(5000)
    .setTimeout(10000)
    .setDatabase(0)
    .setPassword(password)
    .setConnectTimeout(10000);
    return Redisson.create(config);
    }

    /**
     * 可以不注册成bean,直接使用redissonClient来创建Bloom过滤器
     * @param redissonClient
     * @return
     */
   @Bean
   public RBloomFilter<String> bloomFilter(RedissonClient redissonClient) {
      RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("bloom");
      bloomFilter.tryInit(1000000L, 0.01);
      return bloomFilter;
   }

}
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DataApplication.class)
@Slf4j
public class BloomTest {

    @Autowired
    private RedissonClient redissonClient;

    RBloomFilter<String> bloomFilter;

    @Before
    public void init()
    {
        bloomFilter = redissonClient.getBloomFilter("bloom");
        bloomFilter.tryInit(10000L, 0.01);
    }

    /**
     * 测试耗时和误判率
     */
    @Test
    public void test()
    {
        long start = System.currentTimeMillis();

        int total=10000;
        for (int i = 0; i < total; i++)
        {
            bloomFilter.add(String.valueOf(i));
        }
        long end= System.currentTimeMillis();
        log.info("插入用时:{}",end-start);
        int count = 0;
        for (int i = total; i < total+1000; i++)
        {
            if(bloomFilter.contains(String.valueOf(i))){
                count++;
                log.info("误判了:{}",i);
            }
        }
        log.info("插入用时:{}",System.currentTimeMillis()-end);
        log.info("count为:{},误判率:{}",count,(count*1.0/1000));
    }

    /**
     * 获取count
     */
    @Test
    public void countBloomTest()
    {

        long count = bloomFilter.count();
        log.info("count为:{}",count);
    }

    /**
     * 删除过滤器
     */
    @Test
    public void delBloomTest()
    {
        bloomFilter.delete();
    }


}

1万的数据插入差不多用了4分钟,查询1000个数据用了24秒
在这里插入图片描述
在redis可视化中看到的数据如下
在这里插入图片描述

在这里插入图片描述

六.源码解析

布隆过滤器初始化源码,保存的信息(size,hashIterations,expectedInsertions,falseProbability),跟上图匹配,计算位数组大小和哈希个数是数学计算公式
在这里插入图片描述
在这里插入图片描述

参考:
https://zhuanlan.zhihu.com/p/622044226

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

9.2 栅格图层符号化单波段灰度渲染

文章目录 前言单波段灰度QGis设置为单波段灰度二次开发代码实现单波段灰度 总结 前言 介绍栅格图层数据渲染之单波段灰度显示说明&#xff1a;文章中的示例代码均来自开源项目qgis_cpp_api_apps 单波段灰度 以“3420C_2010_327_RGB_LATLNG.tif”数据为例&#xff0c;在QGis中…

RTK_ROS_导航(2):卫星图查看

目录 1. 基于MapViz的卫星图查看 1. 基于MapViz的卫星图查看 安装 # 源码安装 mkdir -p RTK_VISION/src cd RTK_VISION/src git clone https://github.com/swri-robotics/mapviz.git --branchmelodic-eol sudo apt-get install ros-$ROS_DISTRO-mapviz ros-$ROS_DISTRO-mapviz-…

Idea-单个窗口导入并开启多个module项目

前言 大家是否有过这样的困扰&#xff0c;我们每次打开一个项目就需要单开一个idea窗口&#xff0c;项目少时了还好&#xff0c;一旦涉及多个项目间服务调用&#xff0c;特别是再包括网关、注册中心、前端web服务&#xff0c;需要开启的窗口就会是一大批&#xff0c;每次切换的…

B端全局导航:左侧还是顶部?不是随随便便,有依据在。

一、什么是全局导航 B端系统的全局导航是指在B端系统中的主要导航菜单&#xff0c;它通常位于系统的顶部或左侧&#xff0c;提供了系统中各个模块和功能的入口。全局导航菜单可以帮助用户快速找到和访问系统中的各个功能模块&#xff0c;提高系统的可用性和用户体验。 全局导航…

二叉树树的知识,选择➕编程

在一棵深度为7的完全二叉树中&#xff0c;可能有多少个结点&#xff1f;&#xff08;1层深度为1&#xff0c;节点个数为1&#xff09; 对于深度 d的完全二叉树&#xff1a; 完全二叉树中&#xff0c;前 d−1层是满的。 最后一层&#xff08;第 d 层&#xff09;可以不满&#x…

【vue3|第16期】初探Vue-Router与现代网页路由

日期:2024年7月6日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^ 1.01365 = 37.7834;0.99365 = 0.0255 1.02365 = 1377.4083…

前端工程师

15年前&#xff0c;前端主流的框架jquery&#xff0c;那个时候还没有前端工程师,后端开发人员既要写后台业务逻辑&#xff0c;又要写页面设计&#xff0c;还要应付IE不同版本浏览器兼容问题&#xff0c;非常的繁琐、难搞。 现在前端框架很多、很强大&#xff0c;前端开发工程师…

MySQL——第一次作业

部署MySQL 8.0环境 1&#xff0c;删除之前存在的MySQL程序 控制面板删除 2&#xff0c;删除完成后下载MySQL 官网&#xff1a; https://www.mysql.com 在window下下载MSI版本 3&#xff0c;自定义安装 4&#xff0c;配置环境变量 1&#xff0c;系统高级系统设置 2&#xff…

YOLOV8 + PYQT5单目测距—风险类别检测(五)

YOLOV8 PYQT5单目测距 1. 相关配置2. 测距源码3. PYQT环境配置4. 实验结果4.1 界面4.2 界面卡住解决方案 5. 实现效果 1. 相关配置 系统&#xff1a;win 10 YOLO版本&#xff1a;yolov8 拍摄视频设备&#xff1a;安卓手机 电脑显卡&#xff1a;NVIDIA 2080Ti&#xff08;CPU也…

【Python】 已解决:ValueError: document with multiple roots

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ValueError: document with multiple roots 一、分析问题背景 在Python编程中&#xff0c;处理XML或HTML文档时&#xff0c;有时会遇到“ValueError: document …

安防监控视频平台LntonAIServer视频智能分析平台行人入侵检测算法

在当今社会&#xff0c;随着科技的迅速发展和安全需求的日益增长&#xff0c;行人入侵检测技术成为了安全防护领域的重要研究方向。LntonAIServer行人入侵检测算法作为该领域的先进技术之一&#xff0c;其性能和应用效果受到了广泛关注。 首先&#xff0c;从技术角度来看&#…

【线程安全】线程互斥的原理

文章目录 Linux线程互斥线程互斥相关概念互斥量mutex引出线程并发问题引出互斥锁、互斥量 互斥量的接口初始化互斥量销毁互斥量互斥量加锁和解锁使用互斥锁抢票 可重入和线程安全概念&#xff1a;常见线程不安全的情况常见线程安全的情况常见不可重入的情况常见可重入情况可重入…

中霖教育怎么样?中级经济师证书领取流程介绍

在成功通过中级经济师考试之后&#xff0c;需要等待约2到3个月的时间&#xff0c;会发布相关领证公告。 在准备材料方面&#xff0c;考生需确保携带以下文件&#xff1a;身份证件、学历证明以及工作年限的证明文件等&#xff0c;前往相应的人事考试局进行资格审核。 资格审核…

探索交通安全新前沿:构建全面精准的交通事故数据集(目标检测)

亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 在21世…

Redis基础教程(十八):Redis管道技术

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

tomcat 安装和优化

tomcatat tomcat和http一样&#xff0c;都是用来处理动态页面的 tomcat也可以作为web服务器&#xff0c;开源的 php.php tomcat.jsp nginx.html tomcat使用java代码写的程序&#xff0c;运行的是java的web服务程序 tomcat的特点和功能&#xff1a; 1、servlet容器&…

【硬核科普】Ubuntu系统详细解析以及与深度学习的关系

文章目录 0. 前言1. Ubuntu的来源1.1 从Linux说起1.2 开源、稳定的Debian1.3 更稳定、友好且开放的Ubuntu 2. Ubuntu与深度学习3. Ubuntu在自动驾驶领域的应用4. 附录&#xff1a;Linux发行版统计 0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己学习的理…

白蛇插画:成都亚恒丰创教育科技有限公司

白蛇插画&#xff1a;古韵今风&#xff0c;情深意长 在浩瀚的艺术长河中&#xff0c;插画作为一种独特的艺术形式&#xff0c;以其生动形象的画面、丰富多彩的色彩和深邃悠远的意境&#xff0c;成都亚恒丰创教育科技有限公司深受人们喜爱。而“白蛇插画”&#xff0c;作为融合…

图像识别和目标检测在超市电子秤上的应用

目录 前言深度学习的目标检测图像识别技术视觉秤的优势其他应用场景中的技术应用未来展望 前言 随着科技的不断发展&#xff0c;电子秤在生鲜超市中的应用也在不断升级。传统的电子秤需要打秤人员手动输入秤码&#xff0c;这不仅耗时费力&#xff0c;还需要大量的培训以记住各…

Zabbix 6.0 组件 工作原理和组件

Zabbix组件 C/S架构 服务端&#xff1a;zabbix server&#xff08;端口10051&#xff09;&#xff1a;zabbix服务端进程&#xff0c;用于接收代理端发来的监控指标数据&#xff0c;配置和管理zabbix应用程序&#xff0c;也是监控系统的告警中心&#xff08;通过监控项告警触…