什么是布隆过滤器?——超详细解析【建议收藏】

2023-11-03

目录

1、什么是布隆过滤器?

2、实现原理

2.1、回顾哈希函数

2.1.1、哈希函数概念

2.1.2、散列函数的基本特性:

2.2、布隆过滤器数据结构

3、特点

3.1、支持删除吗?

3.2、优点

3.3、缺点

3.4、误判率

4、如何选择哈希函数个数和布隆过滤器长度?

5、手动模拟实现布隆过滤器

整体代码:

5.1、添加元素

5.2、查询元素

5.3、测试:

 6、guava实现布隆过滤器

7、布隆过滤器适用场景


1、什么是布隆过滤器?

布隆过滤器本质上是一种数据结构,是一种巧妙的概率型数据结构,用来高效的插入和查询,是用来告诉使用者某样东西一定不存在或者可能存在。使用多个哈希函数,将一个数据映射到位图结构中。例:

不了解位图吗?看这篇文章: http://t.csdn.cn/M5vmC


2、实现原理

先来回顾哈希函数吧 ~

2.1、回顾哈希函数

2.1.1、哈希函数概念

        将任意的输入数据转换成特定的输出数据的函数,转换后的数据称为哈希值或哈希编码,也叫散列值。如图:

 

2.1.2、散列函数的基本特性:

  •  如果两个散列值是不相同的【同一函数】,那么这两个散列值的原始输入是不同的。这个特性是散列函数具有确定性的结果,具有这种性质的散列函数称为单向散列函数
  • 散列函数的输入和输出不是唯一对应的关系,如果两个散列值相同,两个输入值很可能是相通的,但也可能是不同的,这种情况称为“散列碰撞”。

当我们存储海量数据时,哈希的空间效率很低,当只有一个哈希函数时,很容易发生哈希碰撞~ 

2.2、布隆过滤器数据结构

布隆过滤器是一个由固定大小的二进制向量或者位图和一系列映射函数所组成的。

在初始状态下,对于一个长度为m的位数组,所有位置0,如下:

        当有变量被加入集合时,通过K个映射函数将这个变量映射成位图中的K个点,把它们置为1【举例中以3个映射函数为例】:

 

 查询某个变量的时候,只要这些对应的点是否是都是1:

  • 如果这些点有一个0,则被查询的变量一定不存在
  • 如果都是1,则被查询的变量可能存在

为什么说可能存在,而不是一定存在呢?

        那是因为映射函数本身就是散列函数,散列函数就是会有碰撞哒~


3、特点

3.1、支持删除吗?

布隆过滤器不能直接支持删除操作,因为在删除一个元素时,可能会影响其他元素

例:

         当我们要删除obj1时,需要将4处置0,而此时obj2的hash3也是映射到4处,就会出现后续的查询有问题~

实现删除方案:

将布隆过滤器中的每个比特位扩展成一个小的计数器,插入元素是给计数器加一,删除元素时,减一【通过占用几倍存储空间来增加删除操作】

此方案的缺点:

  • 无法确认元素是否真正在布隆过滤器中【误判】
  • 存在计数回绕【溢出】

3.2、优点

  • 增加和查询元素的时间复杂度为O(k)【k为哈希函数的个数】,与数据量大小无关
  • 哈希函数相互之间没有关系,方便硬件并行运算
  • 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有较大优势
  • 在能够承受一定误判时,布隆过滤器比其他数据结构有很大的空间优势
  • 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能
  • 使用同一组散列函数的布隆过滤器可以进行交、并、差运算

3.3、缺点

  • 有误判率,即存在假阳性,即不能准确判断元素是否在集合中【补救:再建立一个白名单,存储可能会误判的数据】
  • 不能获取元素本身
  • 一般情况,不能从布隆过滤器中删除元素

3.4、误判率

布隆过滤器的误判是指多个输入经过哈希之后在相同的bit位置1了,这样就无法判断究竟是哪个输入产生的,因此误判的根源在于相同的 bit 位被多次映射且置 1。

这种情况也造成了布隆过滤器的删除问题,因为布隆过滤器的每一个 bit 并不是独占的,很有可能多个元素共享了某一位。


4、如何选择哈希函数个数和布隆过滤器长度?

需要使用,套公式即可 ~ 


5、手动模拟实现布隆过滤器

整体代码:

import java.util.BitSet;

class SimpleHash {

    public int cap;//当前容量
    public int seed;//随机

    public SimpleHash(int cap,int seed) {
        this.cap = cap;
        this.seed = seed;
    }

    //模仿库中哈希写哈希函数:
    //根据seed的不同,创建不同的哈希函数
    int hash(String key) {
        int h;
        return (key == null) ? 0 : (seed * (cap-1)) & ((h = key.hashCode()) ^ (h >>> 16));
    }

}
public class MyBloomFilter {
    //导入库中的位图
    public BitSet bitSet;

    //记录存储了多少数据
    public int usedSize;

    //随机种子
    public static final int[] seeds = {3,5,9,11,15,19,25,31};//这里面的数字是随便设置的

    public SimpleHash[] simpleHashes;

    public static final int SIZE = 1 << 20;//这个20是随意给的

    public MyBloomFilter() {
        bitSet = new BitSet(SIZE);
        simpleHashes = new SimpleHash[seeds.length];

        for(int i = 0;i<simpleHashes.length;i++) {
            simpleHashes[i] = new SimpleHash(SIZE,seeds[i]);
        }
    }

    /**
     * 添加数据 到布隆过滤器
     * @param val
     */
    public void add(String val) {
        //3个哈希函数,分别处理当前的数据
        //把他们都存储在位图中即可

    }

    /**
     * 是否包含val,会存在误判
     * @param val
     * @return
     */
    public boolean contains(String val) {

    }

}

补充上述代码空缺部分:

5.1、添加元素

    /**
     * 添加数据 到布隆过滤器
     * @param val
     */
    public void add(String val) {
        //3个哈希函数,分别处理当前的数据

        for (SimpleHash simpleHash : simpleHashes) {
            int index = simpleHash.hash(val);
            //把他们都存储在位图中即可
            bitSet.set(index);
        }
        usedSize ++;
    }

5.2、查询元素

    /**
     * 是否包含val,会存在误判
     * @param val
     * @return
     */
    public boolean contains(String val) {
        for (SimpleHash simpleHash : simpleHashes) {
            int index = simpleHash.hash(val);
            boolean flg = bitSet.get(index);
            if(!flg) {
                return false;
            }
        }
        return true;
    }

5.3、测试:

    //测试
    public static void main(String[] args) {
        MyBloomFilter myBloomFilter = new MyBloomFilter();
        myBloomFilter.add("baidu1");
        myBloomFilter.add("baidu2");
        myBloomFilter.add("tencent");

        System.out.println(myBloomFilter.contains("baidu1"));//true
        System.out.println(myBloomFilter.contains("haha"));//false
    }

 6、guava实现布隆过滤器

  • 创建一个maven项目
  • 导入依赖
  • 测试

 依赖:

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>

测试:

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;


public class Test {
    private static int size = 1000000;//预计要插入多少数据

    private static double fpp = 0.01;//期望的误判率

    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, fpp);

    public static void main(String[] args) {
        //插入数据
        for (int i = 0; i < 1000000; i++) {
            bloomFilter.put(i);
        }
        int count = 0;
        for (int i = 1000000; i < 2000000; i++) {
            if (bloomFilter.mightContain(i)) {
                count++;
                System.out.println(i + "误判了");
            }
        }
        System.out.println("总共的误判数:" + count);
    }
}

 测试结果:


7、布隆过滤器适用场景

  • 网页爬虫中对URL的去重,避免爬取相同的URL地址
  • 垃圾邮件过滤,从数十亿个垃圾邮件列表中判断邮箱是否是垃圾邮箱
  • 秒杀系统,查看用户是否重复购买
  • 数据库防止穿库。 Google Bigtable,HBase 和 Cassandra 以及 Postgresql 使用BloomFilter来减少不存在的行或列的磁盘查找。避免代价高昂的磁盘查找会大大提高数据库查询操作的性能。
  • 业务场景中判断用户是否阅读过某视频或文章,比如抖音或头条,当然会导致一定的误判,但不会让用户看到重复的内容。
  • 缓存宕机、缓存击穿场景,一般判断用户是否在缓存中,如果在则直接返回结果,不在则查询db,如果来一波冷数据,会导致缓存大量击穿,造成雪崩效应,这时候可以用布隆过滤器当缓存的索引,只有在布隆过滤器中,才去查询缓存,如果没查询到,则穿透到db。如果不在布隆器中,则直接返回。
  • WEB拦截器,如果相同请求则拦截,防止重复被攻击。用户第一次请求,将请求参数放入布隆过滤器中,当第二次请求时,先判断请求参数是否被布隆过滤器命中。可以提高缓存命中率。Squid 网页代理缓存服务器在 cache digests 中就使用了布隆过滤器。Google Chrome浏览器使用了布隆过滤器加速安全浏览服务
  • Venti 文档存储系统也采用布隆过滤器来检测先前存储的数据。
  • SPIN 模型检测器也使用布隆过滤器在大规模验证问题时跟踪可达状态空间

好啦!!!我们下期再见咯~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么是布隆过滤器?——超详细解析【建议收藏】 的相关文章

  • 机器学习(一)svm运用实例

    机器学习 一 svm运用实例 这里我使用sklearn svm SVC函数 首先介绍一下函数参数 sklearn svm SVC C 1 0 kernel rbf degree 3 gamma auto coef0 0 0 shrinkin
  • TCPIP四层协议

    TCP IP四层协议 在说TCP IP四层协议之前 就不得不说OSI七层模型 OSI七层模型 自底向上依次是物理层 数据链路层 网络层 传输层 会话层 表示层 应用层 TCP IP体系结构的优点 1 简化了计算机网络的结构 从原来的七层模型
  • UITabBarItem

    UITabBarController UITabBar UIBarItem UITabBarItem UITabBarItem就是UITabBar上显示的小按钮 我们也可以定制系统UITabBarItem按钮 只需通过UITabBarIte

随机推荐

  • C/C++的64位整型 zz

    为了和DSP兼容 TSint64和TUint64设置成TSint40和TUint40一样的数 结果VC中还是认为是32位的 显然不合适 typedef signed long int TSint64 typedef unsigned lon
  • 初始化 Repo错误 错误信息:fatal: error [Errno 111] Connection refused

    错误信息 fatal error Errno 111 Connection refused 解决方法 修改home 目录下的 bashrc文件 gedit bashrc 在文件的末尾添加如下命令 export PATH bin PATH e
  • QT5.6静态编译添加ODBC数据库

    qt5 6已经编译好 现在添加ODBC数据库的支持 1 进入qt everywhere opensource src 5 6 3 qtbase src plugins sqldrivers odbc目录 运行qmake exe 然后再运行n
  • C语言学生管理系统课程设计

    include
  • cookie和session之间的关系

    当登录接口依赖token的 可以先登录后 token存到一个yaml或者json或者ini的配置文件里面 后面所有的请求去拿这个数据就可以全局使用 如果是cookies的参数 可以用session自动关联 详情如下 一 cookie与ses
  • 超全!深度学习在计算机视觉领域的应用一览

    计算机视觉领域正在从统计方法转向深度学习神经网络方法 计算机视觉中仍有许多具有挑战性的问题需要解决 然而 深度学习方法正在针对某些特定问题取得最新成果 在最基本的问题上 最有趣的不仅仅是深度学习模型的表现 事实上 单个模型可以从图像中学习意
  • MySQL查询数据库中所有表名及注释等信息

    1 查询所有表名 select table name from information schema tables where table schema 当前数据库 2 查看所有字段和字段注释 SELECT COLUMN NAME 字段 c
  • torch.Size理解

    torch Size括号中有几个数字就是几维 第一层 最外层 中括号里面包含了两个中括号 以逗号进行分割 这就是 2 3 4 中的2 第二层中括号里面包含了三个中括号 以逗号进行分割 这就是 2 3 4 中的3 第三层中括号里面包含了四个数
  • Python中MD5加密

    MD5是什么 下面的概念是百度百科的 Message Digest Algorithm MD5 中文名为消息摘要算法第五版 为计算机安全领域广泛使用的一种散列函数 用以提供消息的完整性保护 该算法的文件号为RFC 1321 R Rivest
  • ev3编程 python_乐高 EV3 高级编程 - 第四课:Python 模块

    译者按 使用 ev3dev Linux 系统并用 Python 编程的人数比例很低 好像这一课这样写 Python 编程的就更少了 你会发现程序的重用率会大大的提高 EV3 Lesson 4 Python Modules EV3 第 4 课
  • win10 电脑 .Net framework3.5 组件无法安装0x800f801f

    最近在win10上安装了MotorControl Workbench 5 4 0软件需要用到 Net framework3 5 但是安装Net framework3 5老是出错 无论是下载离线安装包安装 还是通过 控制面板 中 程序 的 启
  • 【SSM框架系列】Spring IoC(控制反转) & DI(依赖注入)

    Spring是什么 Spring是分层的 Java SE EE应用 full stack 轻量级开源框架 以 IoC Inverse Of Control 反转控制 和 AOP Aspect Oriented Programming 面向切
  • 指数增强(股票)——Python量化

    指数增强策略 目录 指数增强策略 1 策略原理 2 策略步骤 3 策略代码 4 回测结果和稳健性分析 1 策略原理 说到指数增强 就不得不说指数 在进行股票投资时 有一种分类方式是将投资分为主动型投资和被动型投资 被动型投资是指完全复制指数
  • python对dataframe中series的json格式解析

    方法1 如果df里只有一列json格式 可以保存为txt 然后再删掉列名 在进行处理 import pandas as pd result with open r C Users Administrator Desktop json处理 t
  • 【你不知道的JavaScript】(05)作用域+闭包+编译执行过程

    本文章仅针对我自己在看书过程中对一些不太清楚的知识点进行查漏补缺 你不知道的JavaScript 上卷 第一部分作用域和闭包 编译与执行 传统编译语言的编译过程 词法分析 语法分析 代码生成 而JavaScript语言则要更复杂 JS引擎不
  • mac 访问钥匙串中创建系统证书失败 未知错误的解决方案

    If you cannot store the certificate in the System keychain create it in the login keychain then exported it You can then
  • 慢日志分析工具mysqldumpslow

    慢查询分析工具mysqldumpslow mysqldumpslow OPTS LOGS 后跟参数以及log文件的绝对地址 s 按照那种方式排序 c 访问计数 l 锁定时间 r 返回记录 al 平均锁定时间 ar 平均访问记录数 at 平均
  • c#和js的交互(转)

    如何在 C 中访问 JavaScript 函数 答案如下 c 代码中执行 javaScript 函数 方法一 1 Page RegisterStartupScript ggg 方法二 使用 Literal 类 然后 private void
  • Flutter实战项目-第四篇 页面路由、provider状态管理

    概要 页面路由配置 provider 一 路由配置 创建router dart用于管理所有的路由 然后再main dart MaterialApp中注册路由 router dart中第一个routeName 即是默认打开的页面 import
  • 什么是布隆过滤器?——超详细解析【建议收藏】

    目录 1 什么是布隆过滤器 2 实现原理 2 1 回顾哈希函数 2 1 1 哈希函数概念 2 1 2 散列函数的基本特性 2 2 布隆过滤器数据结构 3 特点 3 1 支持删除吗 3 2 优点 3 3 缺点 3 4 误判率 4 如何选择哈希