目录

  • 布隆过滤器是啥?
  • bitmap
  • 布隆过滤器的实现方式
  • 降低布隆过滤器误判率的方式
  • 总结
  • 布隆过滤器的实现方式
    • 谷歌Guava实现的布隆过滤器
    • 基于Redisson的布隆过滤器
    • 基于rebloom的布隆过滤器
  • 布隆过滤器的使用场景
  • 布隆过滤器的其他进阶实现
  • 布谷鸟过滤器

布隆过滤器是啥?

布隆过滤器是一种判断某个元素是否存在于某个大量集合的算法。
比如:比如现在有一个集合,保存了10亿个手机号码,现在我要判断某个手机号码是否存在于这个集合中。要怎么判断呢?

  1. 最简单的方法,就是遍历集合,挨个判断。这种方式对于少量数据可行,但是对于这种海量数据,首先要保存10亿个号码,本身就会浪费大量的空间。更不要说查找效率了,极低。
  2. 使用Map,通过hash值来进行查找。类似java的HashMap,但是仍然需要将10亿条数据保存起来,很浪费空间。而且,这大量的数据会产生大量的hash冲突,结果就是产生hash冲突的数据,仍然会进行遍历进行挨个比对,这样对内存空间和查询效率的提升,仍然是有限的。

既然上面2种方式对于海量数据不太可行,那么有没有什么更好的方式能解决呢?
布隆过滤器就是为了解决这种问题而产生的。

布隆过滤器底层基于bitmap和若干个hash算法来实现的。所以在了解布隆过滤器之前,首先要了解以下bitmap。

bitmap

bitmap也叫做位图,是一种数据结构。可以理解为是一个很长的数组,每一个数组元素是一个二进制值,非0即1,也就是说bitmap本质上是一个数组,每个数组元素是一个位的值。而每一位的值只能是0或1。

现在我们假设,如果我们将这10亿条数据,通过某种hash算法,判断出每一条数据在该bitmap中的索引,并将该位标记为1。后续如果判断某个数据是否存在时,只需要将该数据也通过同样的方式获得索引位置,然后判断该位的值是否为1,如果为1则存在,如果不为1则不存在。

因为bitmap每一位是一个bit,那么如果通过bitmap来存在10亿个int类型,bitmap的大小为10亿/8/1024/1024 = 0.12G,可以发现通过为位图来表示10亿个整数值仅仅只需要120M大小的空间就可以表示,占用的内存大小大大减少。

但是很遗憾的是,我们上面的假设,是不会产生hash冲突的情况,真实情况是,目前没有一种hash算法可以为每条数据都算出一个唯一的索引并保证不会产生hash冲突。

那么要怎么解决呢?

布隆过滤器的实现方式

布隆过滤器的解决方式就是,通过多个hash算法,为数据算出多个在bitmap中的索引位置,并将这多个索引位置的值都置为1。后续如果判断数据是否存在时,也判断这多个索引位的值是否都为1。如果都为1,则存在,有一个不为1,就说明不存在。这种方式可以大大的降低hash冲突的概率。

不过值得注意的是,布隆过滤器仍然存在一些误判的情况:

  1. 虽然使用多个hash算法,可以大大降低hash冲突的概率,但是在海量数据面前,仍然会存在一些极端情况,所以还是会存在hash冲突的可能性。造成误判。
  2. 还有一种情况,比如上图,加入我现在需要判断数据c是否存在于上面的bitmap中,如果我计算出c在bitmap中的索引位置为: 3、4、5, 但是因为a所计算出的索引位置为0、3、5, b计算出的索引位置是4、6、7。 a和b加起来正好将3、4、5索引位都置为了1,那么c将会被判定为存在于集合中。但是事实是c并不存在这个bitmap中。 这也造成了误判。

这也是布隆过滤器的特点: 存在误判的行为。如果布隆过滤器判断存在,则很有可能存在,有极低的可能不存在。

降低布隆过滤器误判率的方式

  1. 增加hash算法的数量。
    作用:减少hash碰撞的概率(上面第一种情况)。
  2. 增加bitmap的长度。
    作用: 减少hash碰撞的概率(上面第一种情况),减少索引占位重复的概率(上面第二种情况)。

不过需要注意的是:误判率越低,计算效率就会越差,耗费时间就越长。这个需要在实际应用中进行权衡。

总结

  • 布隆过滤器是计算一个元素是否在一个超大集合中的算法
  • 布隆过滤器如果判断数据存在,则很有可能存在;如果判断数据不存在,则一定不存在
  • 降低误判率的方式可以通过增加hash算法或者增加bitmap长度来实现,但是会对计算的效率有影响
  • 布隆过滤器不能删除数据, 因为bitmap中的索引位是公用的,删除了一个可能导致连带删除了别的数据的hash索引位,结果就是:这个数据后续判断不存在,但其实是存在的。

布隆过滤器的实现方式

布隆过滤器目前有3种实现方式

  1. google的 guava
  2. redisson
  3. redis的 reBloom.so插件

谷歌Guava实现的布隆过滤器

  1. 引入依赖
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>21.0</version>
</dependency>
  1. 代码实现(模拟)
public class BloomFilterService{    private static int size = 10000000;//预计要插入多少数据private static double fpp = 0.01;//期望的误判率private BloomFilter<Integer>  bf;/**** 向布隆过滤器中添加数据*/public void addToBloomFilter() {//创建布隆过滤器, 如果不传 fpp参数,默认误判率为0.03bf = BloomFilter.create(Funnels.integerFunnel(), size, fpp);// 模拟向布隆过滤器中添加10亿个数据for(int i =1; i<= size; i++) {bf.put(i);}}/**** 判断数据是否存在*/public boolean exists(int value){return bf.mightContain(value);}
}

这种过滤器的实现方式,是将bitmap存储,hash运算都放在了客户端上,由客户端来实现。

基于Redisson的布隆过滤器

  1. 引入依赖
 <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.10.6</version></dependency>
  1. 代码实现
@Service
public class BloomFilterService{@Autowiredprivate RedissonClient redissonClient;private static long size = 10000000L;//预计要插入多少数据private static double fpp = 0.03;//期望的误判率// 自定义布隆过滤器的 keyprivate String BLOOM_FILTER_KEY = "filter";/**** 向布隆过滤器中添加数据, 模拟向布隆过滤器中添加10亿个数据*/public void addToBloomFilter() {// 获取布隆过滤器RBloomFilter<Integer> bloomFilter = redissonClient.getBloomFilter(BLOOM_FILTER_KEY);// 初始化,容量为10亿, 误判率为0.03bloomFilter.tryInit(size,fpp);// 模拟向布隆过滤器中添加10亿个数据for (int i = 1; i <= size; i++) {bloomFilter.add(i);}}/**** 判断数据是否存在*/public boolean contains(int value) {// 获取布隆过滤器RBloomFilter<Integer> bloomFilter = redissonClient.getBloomFilter(BLOOM_FILTER_KEY);// 判断是否存在return bloomFilter.contains(value);}
}

这种过滤器的实现方式,是将hash运算都放在了客户端上,由客户端来实现, 而把 bitmap存储放在了redis上,由redis来负责。

基于rebloom的布隆过滤器

  1. 下载rebloom
git clone git://github.com/RedisLabsModules/rebloom
cd rebloom
make
  1. 修改redis配置文件,引入rebloom

在redis.conf配置文件中,加入如下配置:
配置reloom文件下的rebloom.so 路径

loadmodule /path/rebloom.so
  1. 重启redis
  2. 向过滤器中添加数据
[root@mysql01 ~]# redis-cli
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> BF.add myBloom 1
127.0.0.1:6379> BF.add myBloom 2
  1. 判断数据是否存在
[root@mysql01 ~]# redis-cli
127.0.0.1:6379>
127.0.0.1:6379> BF.exists myBloom 1

这种过滤器的实现方式,是将hash运算和 bitmap存储都放在了redis上,由redis来负责。

布隆过滤器的使用场景

  • 爬给定网址的时候对已经爬取过的URL去重;
  • 邮箱的垃圾邮件过滤;
  • 黑名单、白名单的校验;
  • 海量数据判重;
  • 防止缓存穿透,将存在的数据放到布隆过滤器中,当访问不存在的数据时迅速返回,避免穿透进入数据库查询。

布隆过滤器的其他进阶实现

  1. Counting Bloom Filter
  2. Spectral Bloom Filter
  3. Dynamic Count Filter
    以上三种过滤器的实现,参考:Bloom Filter 系列改进实现

布谷鸟过滤器

参考:Redis布隆过滤器与布谷鸟过滤器

布隆过滤器及实现方式总结相关推荐

  1. Redis中布隆过滤器的使用及原理

    <玩转Redis>系列文章主要讲述Redis的基础及中高级应用.本文是<玩转Redis>系列第[11]篇,最新系列文章请前往公众号"zxiaofan"查看, ...

  2. 布隆过滤器 redis_redis布隆过滤器

    一布隆过滤器简介 布隆过滤器(Bloom Filter)是 1970 年由布隆提出的类似于Set的数据结构.它实际上是一个很长的二进制向量和一系列随机映射函数.布隆过滤器可以用于检索一个元素是否在一个 ...

  3. java项目中布隆过滤器和布谷鸟过滤器

    布隆过滤器 布隆过滤器是一个叫"布隆"的人提出的,它本身是一个很长的二进制向量,既然是二进制的向量,那么显而易见的,存放的不是0,就是1. 现在我们新建一个长度为16的布隆过滤器, ...

  4. Guava布隆过滤器(boomfilter)使用简介

    1 布隆过滤器简介 布隆过滤器是一种空间利用率较高的概率型数据结构,用来测试一个元素是否在集合中.但是存在一定可能,导致结果误判.即元素不在集合中,查询结果却返回元素在集合中. 布隆过滤器一些的性质 ...

  5. 算法学习 (门徒计划)3-2 哈希表与布隆过滤器及经典问题 学习笔记

    算法学习 (门徒计划)3-2 哈希表与布隆过滤器及经典问题 学习笔记 前言 哈希表 哈希操作 冲突处理 开放定址法 再哈希法 公共溢出区 链式地址法 扩容哈希表 设计简易哈希表 总结 布隆过滤器 对比 ...

  6. 玩转Redis-Redis中布隆过滤器的使用及原理

      <玩转Redis>系列文章主要讲述Redis的基础及中高级应用.本文是<玩转Redis>系列第[11]篇,最新系列文章请前往公众号"zxiaofan"查 ...

  7. Guava 布隆过滤器

    在 Guava 项目的11.0版中,一个新的类添加了进来-- BloomFilter(布隆过滤器)类.布隆过滤器是一种独特的数据结构,用以表明元素是否被保存在一个集合(Set)中.有趣的是,布隆过滤器 ...

  8. 布隆过滤器和布谷鸟过滤器详解

    今天和大家分享下布隆过滤器和布谷鸟过滤器 一.布隆过滤器 1.简单介绍 布隆过滤器是用于检索一个元素是否在一个集合中的算法,是一种用空间换时间的查询算法. 2.实现原理 布隆过滤器的存储结构是一个bi ...

  9. 三种去重方式——HashSet、Redis去重、布隆过滤器(BloomFilter)

    三种去重方式 去重就有三种实现方式,那有什么不同呢? HashSet 使用java中的HashSet不能重复的特点去重.优点是容易理解.使用方便. 缺点:占用内存大,性能较低. Redis去重 使用R ...

最新文章

  1. 学会在Unity中创建一个Match-3益智游戏 Learn To Create a Match-3 Puzzle Game in Unity
  2. Exchange Server 2010中控制台用命令设置用户邮箱自动回复
  3. 【已解决】Error attaching to process: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versi
  4. 【uoj#37/bzoj3812】[清华集训2014]主旋律 状压dp+容斥原理
  5. 使用Bootstrap制作右键单击自定义菜单
  6. poj[2230]Watchcow 深搜 欧拉回路
  7. 小觅相机SDK安装与报错解决
  8. sort函数(c语言排序)
  9. python关系图谱_利用Python+Gephi构建LOL全英雄间的关联图谱
  10. 哪款笔记本电脑最适合程序员学习写代码?结果我竟无言以对
  11. Java后台微信点餐小程序开发最新版笔记,Springboot+Mysql+Freemarker+Bootstrap+微信小程序实现扫码点餐小程序,包含语音提示,微信消息推送,网页管理后台
  12. ssis 转换中文字符乱码_SSIS软件包中的字符映射转换
  13. vue中用ref实现父子组件、孙组件、兄弟组件、非亲子孙组件互相调用的方法
  14. 抽拉式服务器显示器拆卸,显示器底座怎么拆卸
  15. 江苏理科生骈体作文——《绿色生活》
  16. CF - E95(div2) -- A. Buying Torches【简单思维】
  17. Sandbox FAQ
  18. 记一次pptp实践经历
  19. 制作一个偏心轮连杆简易六足【内附资料下载链接】
  20. PL2303TA驱动不支援Windows11及后续版本请洽询购买厂商

热门文章

  1. CAD教程:CAD看图软件中如何设置CAD标注样式?
  2. 【C++11新特性】 auto关键字
  3. 傻瓜教学--vmware安装虚拟机系统和多开游戏和共享真机文件
  4. 记一次收获颇丰的思杰南京研发中心之行
  5. 使用npm安装cnpm
  6. npm安装Weex Toolkit
  7. Automapper如何全局配置map条件过滤null值空值对所有映射起效
  8. Win 10+Ubuntu 18.04双系统安装【UEFI+GPT+双硬盘(SSD+HDD)下】
  9. ASO优化之什么原因会导致关键词落榜?
  10. 计算机服务功能有哪些,台式电脑哪些服务不能禁用?或者哪些服务必须禁用?...