布隆过滤器原理介绍和典型应用案例

news2024/9/11 10:01:39

整理自己过去使用布隆过滤器的应用案例和理解

基本介绍

        1970年由布隆提出的一种空间效率很高的概率型数据结构,它可以用于检索一个元素是否在一个集合中,由只存0或1的位数组和多个hash算法, 进行判断数据   【一定不存在或者可能存在的算法】

如果这些bit数组 有任何一个0,则被判定的元素一定不在;  如果都是1则被检元素很可能在

对比bitmap位图,布隆过滤器适合更多类型元素,通过hash值转换

原理:将元素添加到一个bitmap数组中,每个散列函数将元素映射到bitmap数组中的一个位置。如果该位置已经被占用,则将该位置置为1,否则置为0。当要查询一个元素是否存在时,只需要计算该元素的散列值,并检查bitmap数组中对应的位置是否已经被置为1。如果都是1,则该元素可能存在,否则肯定不存在。不存在的一定不存在,存在的不一定存在

优点:占用空间小,查询速度快,空间效率和查询时间都远远超过一般的算法。

缺点:有一定的误识别率,有一定的误识别率,即某个元素可能存在,但实际上并不存在。删除困难,因为无法确定某个位置是由哪个元素映射而来的。

 在线案例:Bloom Filters

布隆过滤器存在误判率,数组越小,所占的空间越小,误判率越高;如果要降低误判率,则数组越长,但所占空间越大
最大限度的避免误差, 选取的位数组应尽量大, hash函数的个数尽量多, 但空间占用的浪费和性能的下降
业务选择的时候, 需要误判率与bit数组长度和hash函数数量的平衡
布隆过滤器不能直接删除元素,因为所属的bit可能多个元素有使用
如果要删除则需要重新生成布隆过滤器,或者把布隆过滤器改造成带引用计数的方式 

应用场景

解决海量数据下非精确过滤的业务场景 

1)垃圾邮件解决方案(垃圾短信、黑名单同理)

        收集一组具有特定特征的垃圾邮件样本,这些样本可以是文本内容或其他特征,比如发件人、收件人等,将这些样本的特征信息进行哈希处理,并将处理后的结果存储在布隆过滤器中。接下来,当有新的电子邮件到达时,将该邮件的特征信息也进行哈希处理,并且与布隆过滤器中的信息进行比较。如果布隆过滤器中存在该邮件的特征信息,则判断该邮件为垃圾邮件;如果不存在,则判断该邮件为正常邮件

2)解决缓存穿透解决方案

        什么是缓存穿透(查询不存在数据),查询一个不存在的数据,由于缓存是不命中的,如发起为id为“-1”不存在的数据。如果从存储层查不到数据则不写入缓存,导致这个不存在的数据每次请求都要到存储层去查询,大量查询不存在的数据,可能DB就挂掉了,是黑客利用不存在的key频繁攻击应用的一种方式。

       方案就是将所有要【缓存的数据】经过处理后存储布隆过滤器中,即对应的bit上是1,当外部请求发起时,首先会把请求的参数通过哈希算法处理,获得相应的哈希值;根据哈希值计算出位数组中的位置。

如果全部计算的hash值对于的bit存储都是1,则表示数据在合理中,从缓存读出(缓存失效则从数据库中取出);

如果计算的hash值对于的bit存储存在一个是0或以上,则表示这条数据不合理,直接返回数据不存在,不查缓存和数据库,如果布隆过滤器认为值不存在,那么值一定是不存在的,无需查询缓存也无需查询数据库;

3)爬虫URL去重解决方案

        需求:大量的网页爬取,通过解析已经爬取页面中的网页链接,然后再爬取这些链接对应的网页,同一个网页链接有可能被包含在多个页面中,会导致爬虫在爬取的过程中,重复爬取相同的网页;

        方案:创建布隆过滤器,根据业务数据量设置位数组的大小,将位数组全部设置为0;
将每个URL地址通过哈希算法处理,获得相应的哈希值;
根据哈希值计算出位数组中的位置,将位数组中的位置设置为1;
当新的URL地址进入时,重复上述步骤计算出对应的位置,检查位数组中的位置是否为0,如果是0,则表示该URL地址一定没被爬取过;
如果URL地址不存在,经过爬虫处理后,则将其对应的位置设置为1,以表示该URL地址已经存在;
重复上述步骤,直到所有的URL地址都处理完毕,完成去重。

POM 依赖
<dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>


    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.12.0</version>
    </dependency>

    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>31.1-jre</version>
    </dependency>

</dependencies>
 @Test
    public void testGeneUrl() {
        try{
            File file = new File("urls.txt");
            if (!file.exists()) {
                file.createNewFile(); // 创建新文件,有同名的文件的话直接覆盖
            }
            FileOutputStream fos = new FileOutputStream(file, true);
            OutputStreamWriter osw = new OutputStreamWriter(fos);
            BufferedWriter bw = new BufferedWriter(osw);
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < 5000000; i++) {
                String name = RandomStringUtils.randomAlphabetic(5);
                String fileName = "https://www." + name + ".com" + i + "\n";
                builder.append(fileName);
            }
            bw.write(String.valueOf(builder));
            bw.newLine();
            bw.flush();
            bw.close();
            osw.close();
            fos.close();
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e2) {
            e2.printStackTrace();
        }
    }

//参数一: 指定布隆过滤器中存的是什么类型的数据,有 IntegerFunnel,LongFunnel,StringCharsetFunnel
//参数二: 预期需要存储的数据量
//参数三: 误判率,默认是 0.03
BloomFilter.create(Funnels.stringFunnel(Charset.forName("UTF-8")), 5000000, 0.01);

 4)分库分表下手机号重复注册解决方案

        一般业务里面的partitionKey是不可变动的,所以不能用手机号作为分片键(换手机号需求是存在的),所以业务里面的分片键,多数是固定的业务id,比如user_id

创建布隆过滤器,根据业务数据量设置位数组的大小,将位数组全部设置为0;
把要注册的手机号通过通过哈希算法处理,获得相应的哈希值;
根据哈希值计算出位数组中的位置,如果对应的位数组中的位置有存在0,则一定是未注册的
如果经过多个hash函数处理,对应的位数组中都是1,则认为是注册过的
最后如果用户注册成功后,将位数组中的位置设置为1

@Bean
  public Set set() throws IOException {
    Set<String> set = new LinkedHashSet<>();
    FileInputStream inputStream = new FileInputStream(new File("urls.txt"));
    InputStreamReader streamReader = new InputStreamReader(inputStream);
    BufferedReader reader = new BufferedReader(streamReader);
    String line = null;
    while (true) {
      line = reader.readLine();
      if (line != null) {
        set.add(line);
      } else {
        break;
      }
    }
    inputStream.close();
    return set;
  }


  @Bean
  public BloomFilter bloomFilter() throws IOException {
    BloomFilter bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("UTF-8")), 5000000, 0.01);
    FileInputStream inputStream = new FileInputStream(new File("urls.txt"));
    InputStreamReader streamReader = new InputStreamReader(inputStream);
    BufferedReader reader = new BufferedReader(streamReader);
    String line = null;
    while (true) {
      line = reader.readLine();
      if (line != null) {
        bloomFilter.put(line);
      } else {
        break;
      }
    }
    inputStream.close();
    return bloomFilter;
  }
  
  
@RestController
@RequestMapping("/api")
public class FilterController {
    @Autowired
    private BloomFilter<String> bloomFilter;

    @Autowired
    private Set set;

    @GetMapping("/bloom")
    public String list() throws IOException {

        //判断是否包含这个内容
        if (bloomFilter.mightContain("https://www.dhVrX.com5")) {
            return "命中了";
        } else {
            return "没命中";
        }
    }

    @GetMapping("/set")
    public String set() {
        if (set.contains("httssps://www.shncb.com999663")) {
            return "命中了";
        } else {
            return "没命中";
        }
    }

}

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

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

相关文章

广告创意的魔力:争议与诱惑并存

《广告创意的魔力&#xff1a;争议与诱惑并存》 一、广告的创意魅力之源 广告创意是广告行业的灵魂&#xff0c;它决定着广告能否在浩瀚的信息海洋中脱颖而出&#xff0c;抓住受众的注意力。优秀的广告创意往往能够打破常规&#xff0c;用新颖、独特、有趣的手法表达广告主题…

D55125ADA A型漏电保护芯片,适用于 110V⁓220V(50/60Hz)电压,可应用于 新能源充电桩(充电枪)、智能空开(智能微断开关)等工业产品

一、应用领域 新能源充电桩&#xff08;充电枪&#xff09;、智能空开&#xff08;智能微断开关&#xff09;等工业产品&#xff0c;以及电热水器、电烤箱、电烤炉等小家电产品。 二、功能介绍 D55125ADA 是一款高性能 CMOS 漏电保护器专用电路。芯片内部包含稳压电源、放大电路…

C是用什么语言写出来的?

C是用什么语言写出来的? C语言的起源和发展是一个迭代过程&#xff1a; 1. 最初的C语言编译器的开发始于对B语言的改进。B语言是由Ken Thompson设计的&#xff0c;它是基于BCPL语言简化而来的。在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「 C语言的…

文件IO(代码案例: 文件复制, 指定目录查找文件, 指定目录查找内容)

文件复制 进行普通文件的复制 使用操作字节流的对象操作文件 // 文件复制 public class Main {public static void main(String[] args) throws IOException {// 输入两个路径, 源路径, 目的路径Scanner scanner new Scanner(System.in);System.out.println("请输入拷贝文…

鸿蒙Harmony应用开发—ArkTS-高级组件:@ohos.arkui.advanced.Chip(操作块组件)

操作块&#xff0c;用于搜索框历史记录或者邮件发送列表等场景。 说明&#xff1a; 该组件从API Version 11开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 Chip Chip({options:ChipOptions}) 装饰器类型&#xff1a;Builde…

springboot网站开发-诡异的static/images读取故障

springboot网站开发-诡异的static/images读取故障!我在本地环境测试代码&#xff0c;一切正常。可以读取到该路径下的图片模板&#xff0c;正常生成图片存储在本地D盘下面的文件夹。但是改成服务器linux环境后就不行了。打包发布后&#xff0c;死活读取不到图片模板。 这个故障…

JavaScript高级(十三)---ES6中Set,map

ES6 Set 在ES6之前&#xff0c;我们存储数据的结构主要有两种&#xff1a;数组、对象。 在ES6中新增了另外两种数据结构&#xff1a;Set、Map&#xff0c;以及它们的另外形式WeakSet、WeakMap。 Set是一个新增的数据结构&#xff0c;可以用来保存数据&#xff0c;类似于数组&a…

python家政服务系统flask-django-php-nodejs

相比于以前的传统手工管理方式&#xff0c;智能化的管理方式可以大幅降低家政公司的运营人员成本&#xff0c;实现了家政服务的标准化、制度化、程序化的管理&#xff0c;有效地防止了家政服务的随意管理&#xff0c;提高了信息的处理速度和精确度&#xff0c;能够及时、准确地…

TDP1000泰克TDP1000差分探头

181/2461/8938产品概述&#xff1a; 高速串行标准中使用的差分信令要求非常精确的检测。泰克差分探头能够提供业界领先的带宽和信号保真度&#xff0c;可确保您能洞察每一个细节。我们的 TriMode™ 架构 使您可以从一个DUT连接点上完成差分、单端和共模测量&#xff0c;进而简…

C语言经典算法-5

文章目录 其他经典例题跳转链接26.约瑟夫问题&#xff08;Josephus Problem&#xff09;27.排列组合28.格雷码&#xff08;Gray Code&#xff09;29.产生可能的集合30.m元素集合的n个元素子集 其他经典例题跳转链接 C语言经典算法-1 1.汉若塔 2. 费式数列 3. 巴斯卡三角形 4. …

JMeter如何监控服务器资源?

jmeter是一个基于Java的开源性能测试工具&#xff0c;它可以用来测试静态和动态的资源&#xff0c;例如Web应用、数据库、FTP服务器等。如果要在进行压力测试的同时&#xff0c;监控服务器的CPU、内存、磁盘、网络等资源的使用情况&#xff0c;需要使用一些插件或工具来实现。 …

【STL基础】vector、stack、queue、list、pair、map、unordered_map、set、unordered_set(详细讲解)

vector、list、pair、unordered_map、unordered_set、stack、queue 参考文章&#xff1a; &#xff08;1&#xff09;【apollo】泛型编程 与 STL &#xff08;2&#xff09;c stack用法 入门必看 超详细 &#xff08;3&#xff09;C中queue的用法&#xff08;超详细&#xff0c…

使用 SCL 给 Centos7.6 升级 GCC 版本

使用 SCL 给 Centos7.6 升级 GCC 版本 什么是 SCL背景安装 SCL安装工具集启用环境devtoolset 与 gcc 版本对应参考文献 什么是 SCL SCL 软件集是为了给 RHEL / CentOS 用户提供一种方便、安全的安装和使用应用程序和运行时环境的多个&#xff08;而且可能是更新的&#xff09;…

最新梨花带雨网页音乐播放器二开优化修复美化版全开源版本源码下载

最新梨花带雨网页音乐播放器二开优化修复美化版全开源版本源码下载 梨花带雨播放器基于thinkphp6开发的XPlayerHTML5网页播放器前台控制面板,支持多音乐平台音乐解析。二开内容:修复播放器接口问题,把接口本地化,但是集成外链播放器接口就不本地化了,我花钱找人写的理解下…

Flutter 3.13 之后如何监听 App 生命周期事件

在 Flutter 中&#xff0c;您可以监听多个生命周期事件来处理应用程序的不同状态&#xff0c;但今天我们将讨论 didChangeAppLifecycleState 事件。每当应用程序的生命周期状态发生变化时&#xff0c;就会触发此事件。可能的状态有 resumed 、 inactive 、 paused 、 detached …

应急响应靶机训练-Web3题解

前言 接上文&#xff0c;应急响应靶机训练-Web3。 前来挑战&#xff01;应急响应靶机训练-Web3 题解 首先登录用户administrator 寻找隐藏用户 找到隐藏用户hack6618$ 然后去找apache的日志文件 分析得出两个IP地址 192.168.75.129 192.168.75.130 然后更换hack6618$的…

【前端】卡片渐变色阴影效果 旋转动画

【前端】卡片渐变色阴影效果 旋转动画 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>Breathing…

【2】华为交换机如何修改Web登录密码?

0x01 问题描述 如果忘记了Web登录密码或者希望修改Web登录密码&#xff0c;用户可以通过Console口、STelnet或Tenet等方式登录交换机后设置新的Web登录密码。 使用Telnet协议存在安全风险&#xff0c;建议使用Console囗或STelnet V2登录设备 0x02 问题解决 <HUAWEI> s…

HarmonyOS入门-环境及项目搭建

近来在学习HarmonyOS&#xff0c;虽然跟着入门项目敲了部分代码&#xff0c;但感觉还是有点云里雾里的&#xff0c;并且官方文档和视频课程只能说是一言难尽&#xff0c;所以打算通过写文章的方式记录下。 学习代码最好的方式是通过项目&#xff0c;官方提供的Demo还是挺不错的…

JAVA多线程之JMM

文章目录 1. Java内存模型2. 内存交互3. 三大特性3.1 可见性3.1.1 可见性问题3.1.2 原因3.1.3 解决方法 3.2 原子性3.3 有序性 4. 指令重排5. JMM 与 happens-before5.1 happens-before关系定义5.2 happens-before 关系 在继续学习JUC之前&#xff0c;我们现在这里介绍一下Java…