目录

  • Bloom Filter简介
  • 布隆过滤器的原理
  • 布隆过滤器的实现
    • 使用guava实现
    • 使用redis实现

Bloom Filter简介

Bloom Filter 布隆过滤器,由一个叫布隆的小伙子提出,故而用他的名字来命名,可以判断元素是否在指定集合中。

常见的应用场景

  • 避免缓存击穿
  • 爬虫:过滤新抓取到的url,已抓取存储的就不再处理
  • 黑白名单:过滤垃圾邮件(检测发件邮箱是否在垃圾邮箱集合中),拦截骚扰电话(检测手机号是否在指定号码库中)等等
  • 过滤用户:已签到、未签到,是否为新用户、是否活跃。

优点

  • 使用二进制向量(数组),内存占用极少,空间效率高,存储集合占用的空间比哈希表小得多
  • 存储、查询元素效率高,查询花费的时间比一般算法少得多

缺点

  • 有一定的误判率。可以判断某个数据一定不在集合中或者可能在集合中(也可能不在集合中),可能在集合中(也可能不在)这是必然事件,肯定是正确判断;而一定在集合中则可能存在误判,布隆过滤器判定该数据一定不在集合中,但实际可能在集合中。
  • 删除困难,加载集合后难以删除集合中的元素

bloom filter能做到时间、空间上的高效,是以牺牲判断的准确率、删除的便利性为代价的。

布隆过滤器的原理

布隆过滤器由一串很长的二进制向量和一系列随机映射函数组成,二进制向量可以将看做一个二进制数组,存放的元素是0、1,初始值默认为0。

当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,如果这些点有任何一个0,则被检元素一定不在集合中;如果都是1,则被检元素可能在集合中。

Bloom Filter跟单哈希函数Bit-Map不同之处在于:Bloom Filter使用了k个哈希函数,每个数据跟k个bit对应。从而降低了冲突的概率。

使用bloom filter时,需要预估集合数据量n、确定期望的误判率fpp。误判指的是布隆过滤器判断为一定不在集合中,而实际可能在集合中。

布隆过滤器的实现

布隆过滤器只是一个理论,有多种实现方式,常见的方式有2种

  • 使用google开源的guava实现
  • 使用redis实现

guava使用本地内存存储数据,如果集合元素数量级较大,会占用很大一部分堆内存,此时可以考虑使用专业的内存型服务器redis,但与redis交互有网络通信的时间开销,初始化布隆过滤器时添加集合元素极慢,数据判断也比guava慢一些。

使用guava实现

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.1.1-jre</version>
</dependency>
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;/*** 使用Guava实现的BloomFilter*/
public class GuavaBloomFilter {/*** 预计插入次数(集合中元素的预估数量),此处为 1百万*/private static final int expectedInsertions = 1000000;/*** 期待的误判率,只能为 (0,1) 上的小数,缺省时默认为 0.03 即 3% 判断100个数据大概有3个会误判* 数值越大,对判断结果的准确性要求越低,判断速度越快,误判发生的可能性越大、发生的误判数量越多*/private static final double fpp = 0.001;/*** 布隆过滤器,泛型指定集合元素的类型*/// private static BloomFilter<Integer> bf = BloomFilter.create(Funnels.integerFunnel(), expectedInsertions);private static BloomFilter<Integer> bf = BloomFilter.create(Funnels.integerFunnel(), expectedInsertions, fpp);public static void main(String[] args) {//加载集合元素for (int i = 0; i < expectedInsertions; i++) {bf.put(i);}System.out.println("集合元素加载完毕");//判断检测int errCount = 0;for (int i = 0; i < expectedInsertions + 1000; i++) {//mightContain()判断元素是否可能在集合中,false——一定不在集合中(可能为误判),true——可能在集合中也可能不在if (!bf.mightContain(i)) {System.out.printf("%d可能为误判\n", i);errCount++;}}System.out.printf("判断检测完毕,可能的误判次数为%d", errCount);}}

使用redis实现

redis可通过Bitmap实现布隆过滤器,Bitmap是在字符串类型(Simple Dynamic String,SDS)之上定义的与比特相关的一系列操作,SDS作为bit数组,redis提供了setbit、getbit、bitcount等指令来操作二进制位。

jedis、spring data redis属于操作redis的基础类库,引入基础类库自己实现布隆过滤器很麻烦,可以使用现成的轮子Redisson。Redisson是java中操作redis的一个类库,提供了更上层的封装,功能强大。

<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.16.1</version>
</dependency>
import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;/*** 基于redis实现的布隆过滤器*/
public class RedissonBloomFilter {/*** 预计插入次数(集合中元素的预估数量),此处为 1万*/private static final long expectedInsertions = 10000L;/*** 期待的误判率,(0,1)上的小数* 数值越大,对判断结果的准确性要求越低,判断速度越快,误判发生的可能性越大、发生的误判数量越多*/private static final double falseProbability = 0.001;/*** 获取RedissonClient*/public static RedissonClient getRedissonClient() {Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379");return Redisson.create(config);}public static void main(String[] args) {RedissonClient redissonClient = getRedissonClient();//会把布隆过滤器存储为一个键值对,所有的元素作为一个string进行储存,参数指定key的名称,泛型指定集合元素的类型RBloomFilter<Integer> bf = redissonClient.getBloomFilter("xxx");//初始化布隆过滤器,指定预计插入次数、误判率bf.tryInit(expectedInsertions, falseProbability);//加载集合元素for (int i = 0; i < expectedInsertions; i++) {bf.add(i);}System.out.println("集合元素加载完毕");//判断检测int errCount = 0;for (int i = 0; i < expectedInsertions + 1000; i++) {//contains判断元素是否可能在集合中,false——一定不在集合中(可能为误判),true——可能在集合中也可能不在if (!bf.contains(i)) {System.out.printf("%d可能为误判\n", i);errCount++;}}System.out.printf("判断检测完毕,可能的误判次数为%d", errCount);}}

以上获取的RedissonClient是单机版redis的,如果是redis集群,可以参考https://blog.csdn.net/chy_18883701161/article/details/106380296

Bloom Filter 布隆过滤器相关推荐

  1. 布隆过滤器速度_高并发系统一定要考虑的 Bloom Filter 布隆过滤器

    开篇思考 你能想到哪些方式判断一个元素是否存在集合中? 布隆过滤器并不存储数据本身,那么是怎么做到过滤的? 布隆过滤器实现?参数配置? 一般我们用来判断一个元素是否存在,会想到用 List,Map,S ...

  2. Hash(哈希/散列)和Bloom Filter(布隆过滤器)

    文章目录 Hash(函数/表) Bloom Filter 布隆过滤器的误识别问题 总结 参考 Hash(函数/表) Hash (中译为哈希,或者散列)函数在计算机领域,尤其是数据快速查找领域,加密领域 ...

  3. Bloom Filter(布隆过滤器)

    一.介绍 Bloom Filter是一个有m bits的bit array,每一个bit位都初始化为0.并且定义有k个不同的hash function,每个都以uniform random distr ...

  4. Redis缓存击穿解决办法之bloom filter布隆过滤器

    转载地址:http://blog.jobbole.com/113396/ 布隆过滤器:Google Guava类库源码分析及基于Redis Bitmaps的重构 2017/12/30 · 开发 · B ...

  5. Bloom Filter布隆过滤器(解决redis缓存穿透)

    目录 1.什么是布隆过滤器: 2.用BitSet手写简单的布隆过滤器 3.redis中的缓存穿透 4.Redis中的布隆过滤器 4.1 RedisBloom 4.1.1直接编译进行安装 4.1.2使用 ...

  6. Bloom filter(布隆过滤器)学习与使用总结

    一.简介 当我们使用主流数据结构如 Lists, Maps, Sets, Trees等等时,我可以得到确切的结果,无论这个数据存在或是不存在.概率数据结构能够提供一种基于内存的,快速的查找出一种可能而 ...

  7. Bloom Filter(布隆过滤器)的概念和原理

    Bloom filter 适用范围:可以用来实现数据字典,进行数据的判重,或者集合求交集 基本原理及要点: 对于原理来说很简单,位数组+k个独立hash函数.将hash函数对应的值的位数组置1,查找时 ...

  8. Bloom Filter(布隆过滤器)的概念和原理(转)

    Bloom filter 适用范围:可以用来实现数据字典,进行数据的判重,或者集合求交集 基本原理及要点: 对于原理来说很简单,位数组+k个独立hash函数.将hash函数对应的值的位数组置1,查找时 ...

  9. Hbase-之Bloom Filter布隆过滤器 hbase请求交互

    Hbase-之Bloom Filter布隆过滤器&Hbase 1 BloomFilter是什么? 布隆过滤器,以它的创始人Burton Howard Bloom的名字命名,首先明确一个点,它只 ...

最新文章

  1. mysql连接hang住问题分析
  2. QDir::toNativeSeparators的使用
  3. 剑指offer:调整数组顺序使奇数位于偶数前面
  4. python网站开发linux_使用Python编写Linux系统守护进程实例
  5. c语言第七周答案,2017-mooc-C语言-第七周-答案
  6. CSAPP--整数的表示
  7. js解决客户端与服务器时间不一致的问题
  8. STL_算法_元素计数(count、count_if)
  9. 类的静态成员函数带来了什么好处,应该在什么时候使用?
  10. 【转】文件各种上传,离不开的表单
  11. SpringBoot--自动装配之Import注解以及源码分析
  12. echarts5.0 动态柱状图 不用调接口 不用jQuery舒适应用
  13. Maple 热工计算
  14. python抛出异常 后如何接住_如何在try中捕获异常后继续循环。。。例外
  15. [转载]美国夫妻生活如何在钱上更亲密
  16. 大学计算机组织部面试问题及答案,组织部面试问题及答案(30页)-原创力文档...
  17. LiveChart样式参数介绍
  18. 2019年风险投资人 ( VCPE ) 汇总
  19. slam入门——十四讲笔记(一)
  20. Windows 10 启用telnet client功能

热门文章

  1. 微信公众号/微信小程序获取用户信息以及推送微信模版消息_MQ
  2. Pycharm 常用快捷键大全【快查字典版】
  3. 【图像处理】图形图像中术语
  4. A*算法项目实践之一:栅格法的使用与障碍物栅格的生成
  5. html加入图片如何自动平铺,css怎么让图片平铺?
  6. 1688.item_search_img按图搜索1688商品(拍立淘)API的调用参数和实例
  7. 电脑双核CPU具体是什么意思?
  8. elastic-job VS xxl-job
  9. 阿里云域名解析网络和服务架构设计总概览(一)
  10. Vue与Angular以及React的区别