布隆过滤器工作原理_布隆过滤器的原理

布隆过滤器工作原理_布隆过滤器的原理布隆过滤器(BloomFilter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。hash原理Hash(哈希,或者散列)函数在计算机领域,尤其是数据快速查找领域,加密领域用的极广。其作用是将一个大的数据集

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

hash原理

Hash (哈希,或者散列)函数在计算机领域,尤其是数据快速查找领域,加密领域用的极广。
其作用是将一个大的数据集映射到一个小的数据集上面(这些小的数据集叫做哈希值,或者散列值)

一个应用是Hash table(散列表,也叫哈希表),是根据哈希值 (Key value) 而直接进行访问的数据结构。也就是说,它通过把哈希值映射到表中一个位置来访问记录,以加快查找的速度。下面是一个典型的 hash 函数 / 表示意图:

布隆过滤器工作原理_布隆过滤器的原理

布隆过滤器工作原理_布隆过滤器的原理

哈希函数有以下两个特点:

  • 如果两个散列值是不相同的(根据同一函数),那么这两个散列值的原始输入也是不相同的。
  • 散列函数的输入和输出不是唯一对应关系的,如果两个散列值相同,两个输入值很可能是相同的。但也可能不同,这种情况称为 “散列碰撞”(或者 “散列冲突”)。

缺点: 引用吴军博士的《数学之美》中所言,哈希表的空间效率还是不够高。如果用哈希表存储一亿个垃圾邮件地址,每个email地址 对应 8bytes, 而哈希表的存储效率一般只有50%,因此一个email地址需要占用16bytes. 因此一亿个email地址占用1.6GB,如果存储几十亿个email address则需要上百GB的内存。除非是超级计算机,一般的服务器是无法存储的。

所以要引入下面的 Bloom Filter。

布隆过滤器原理

如果想判断一个元素是不是在一个集合里,一般想到的是将集合中所有元素保存起来,然后通过比较确定。链表、树、散列表(又叫哈希表,Hash table)等等数据结构都是这种思路。但是随着集合中元素的增加,我们需要的存储空间越来越大。同时检索速度也越来越慢。

Bloom Filter 是一种空间效率很高的随机数据结构,Bloom filter 可以看做是对 bit-map 的扩展, 它的原理是:

当一个元素被加入集合时,通过 K 个 Hash 函数将这个元素映射成一个位阵列(Bit array)中的 K 个点,把它们置为 1。检索时,我们只要看看这些点是不是都是 1 就(大约)知道集合中有没有它了:

  • 如果这些点有任何一个 0,则被检索元素一定不在
  • 如果都是 1,则被检索元素很可能在。

布隆过滤器优点

它的优点是
空间效率

查询时间
都远远超过一般的算法,布隆过滤器存储空间和插入 / 查询时间都是常数
O(k)
。另外, 散列函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。

布隆过滤器缺点

但是布隆过滤器的缺点和优点一样明显。误算率是其中之一。随着存入的元素数量增加,
误算率
随之增加。但是如果元素数量太少,则使用散列表足矣。

(误判补救方法是:再建立一个小的白名单,存储那些可能被误判的信息。)

另外,一般情况下不能从布隆过滤器中删除元素. 我们很容易想到把位数组变成整数数组,每插入一个元素相应的计数器加 1, 这样删除元素时将计数器减掉就可以了。然而要保证安全地删除元素并非如此简单。首先我们必须保证删除的元素的确在布隆过滤器里面. 这一点单凭这个过滤器是无法保证的。另外计数器回绕也会造成问题。(google guava实现的布隆过滤器里面就没有包含删除元素)

google guava实现的布隆过滤器简单使用

场景描述:100W个字符串信息放入到布隆过滤器,另外随机生成1W个字符串,判断他们在100W里面是否存在
<dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>19.0</version>
  </dependency>

package com.tlk.guava;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

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

/**
 * google guava 布隆过滤器的使用
 * 
 * @author tanlk 2017年10月24日 下午11:44:16
 */
public class BloomFilterTest {
    private static final int insertions = 1000000;// 100万

    public static void main(String[] args) {
        // 初始化一个存储string数据的布隆过滤器,默认fpp(误差率) 0.03
        BloomFilter<String> bf = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), insertions);

        Set<String> set = new HashSet<String>(insertions);
        List<String> list = new ArrayList<String>(insertions);

        for (int i = 0; i < insertions; i++) {
            String uuid = UUID.randomUUID().toString();
            bf.put(uuid);
            set.add(uuid);
            list.add(uuid);
        }

        int wrong = 0; // 布隆过滤器误判的次数
        int right = 0;// 布隆过滤器正确次数

        for (int i = 0; i < 10000; i++) {
            String str = i % 100 == 0 ? list.get(i / 100) : UUID.randomUUID().toString();
            if (bf.mightContain(str)) {
                if (set.contains(str)) {
                    right++;
                } else {
                    wrong++;
                }
            }
        }

        //right 为100
        System.out.println("right:" + right);
        //因为误差率为3%,所以一万条数据wrong的值在300左右
        System.out.println("wrong:" + wrong);
    }

}

布隆过滤器的应用场景


     
     
     
1.Google著名的分布式数据库Bigtable以及Hbase使用了布隆过滤器来查找不存在的行或列,以减少磁盘查找的IO次数。
2.检查垃圾邮件地址
假定我们存储一亿个电子邮件地址,我们先建立一个十六亿二进制(比特),即两亿字节的向量,然后将这十六亿个二进制全部设置为零。对于每一个电子邮件地址 X,我们用八个不同的随机数产生器(F1,F2, ...,F8) 产生八个信息指纹(f1, f2, ..., f8)。再用一个随机数产生器 G 把这八个信息指纹映射到 1 到十六亿中的八个自然数 g1, g2, ...,g8。现在我们把这八个位置的二进制全部设置为一。当我们对这一亿个 email 地址都进行这样的处理后。一个针对这些 email 地址的布隆过滤器就建成了。
3.Google chrome 浏览器使用bloom filter识别恶意链接(能够用较少的存储空间表示较大的数据集合,简单的想就是把每一个URL都可以映射成为一个bit)
4.文档存储检索系统也采用布隆过滤器来检测先前存储的数据
5.爬虫URL地址去重
A,B 两个文件,各存放 50 亿条 URL,每条 URL 占用 64 字节,内存限制是 4G,让你找出 A,B 文件共同的 URL。如果是三个乃至 n 个文件呢?
分析 :如果允许有一定的错误率,可以使用 Bloom filter,4G 内存大概可以表示 340 亿 bit。将其中一个文件中的 url 使用 Bloom filter 映射为这 340 亿 bit,然后挨个读取另外一个文件的 url,检查是否与 Bloom filter,如果是,那么该 url 应该是共同的 url(注意会有一定的错误率)。
6.解决缓存穿透问题
缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。

伪代码如下:

布隆过滤器工作原理_布隆过滤器的原理

布隆过滤器工作原理_布隆过滤器的原理
布隆过滤器工作原理_布隆过滤器的原理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/185220.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 浅谈 JDBC 中 CreateStatement 和 PrepareStatement 的区别与优劣。

    浅谈 JDBC 中 CreateStatement 和 PrepareStatement 的区别与优劣。微信搜索程序员的起飞之路可以加我公众号,保证一有干货就更新~本人的几点浅见,各位大大不喜勿喷。先说下这俩到底是干啥的吧。其实这俩干的活儿都一样,就是创建了一个对象然后去通过对象调用executeQuery方法来执行sql语句。说是CreateStatement和PrepareStatement的区别,但其实说的就是Statement和PrepareStatement的区别,相信大家在网上已经看到过不少这方面的资料和博客,我在此处提几点,大家看到过的,就当重记忆,没看到就当补充~下面开始谈谈他.

  • 数据格式汇总及type, astype, dtype区别「建议收藏」

    数据格式汇总及type, astype, dtype区别「建议收藏」标签(空格分隔):pythonuint8在此输入正文8位的无符号整形数据取值范围从0到255一singed与unsigned的区别二float改变类型643264to32shape翻倍改变类型321632to16shape翻倍改变类型32float32tofloatshape还原float默认是float64改变类型float64intfloat64

  • SqlHelper

    SqlHelperSqlHelper

  • Redis的安装与配置

    Redis的安装与配置

    2021年10月30日
  • 支持向量机通俗导论(理解SVM的三层境界)

    支持向量机通俗导论(理解SVM的三层境界)支持向量机通俗导论(理解SVM的三层境界)作者:July。致谢:pluskid、白石、JerryLead。说明:本文最初写于2012年6月,而后不断反反复复修改&amp;优化,修改次数达上百次,最后修改于2016年11月。声明:本文于2012年便早已附上所有参考链接,并注明是篇“学习笔记”,且写明具体参考了pluskid等人的文章。文末2013年的PDF是为证。另…

  • lunix常用命令「建议收藏」

    lunix常用命令「建议收藏」文件管理命令ls      显示文件或目录   -l     列出文件详细信息l(list)   -a     列出当前目录下所有文件及目录,包括隐藏的a(all)mkdir    创建目录   -p     创建目录,若无父目录,则创建p(parent)cd   

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号