Bloom Filter 布隆过滤器
目录
- 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 布隆过滤器相关推荐
- 布隆过滤器速度_高并发系统一定要考虑的 Bloom Filter 布隆过滤器
开篇思考 你能想到哪些方式判断一个元素是否存在集合中? 布隆过滤器并不存储数据本身,那么是怎么做到过滤的? 布隆过滤器实现?参数配置? 一般我们用来判断一个元素是否存在,会想到用 List,Map,S ...
- Hash(哈希/散列)和Bloom Filter(布隆过滤器)
文章目录 Hash(函数/表) Bloom Filter 布隆过滤器的误识别问题 总结 参考 Hash(函数/表) Hash (中译为哈希,或者散列)函数在计算机领域,尤其是数据快速查找领域,加密领域 ...
- Bloom Filter(布隆过滤器)
一.介绍 Bloom Filter是一个有m bits的bit array,每一个bit位都初始化为0.并且定义有k个不同的hash function,每个都以uniform random distr ...
- Redis缓存击穿解决办法之bloom filter布隆过滤器
转载地址:http://blog.jobbole.com/113396/ 布隆过滤器:Google Guava类库源码分析及基于Redis Bitmaps的重构 2017/12/30 · 开发 · B ...
- Bloom Filter布隆过滤器(解决redis缓存穿透)
目录 1.什么是布隆过滤器: 2.用BitSet手写简单的布隆过滤器 3.redis中的缓存穿透 4.Redis中的布隆过滤器 4.1 RedisBloom 4.1.1直接编译进行安装 4.1.2使用 ...
- Bloom filter(布隆过滤器)学习与使用总结
一.简介 当我们使用主流数据结构如 Lists, Maps, Sets, Trees等等时,我可以得到确切的结果,无论这个数据存在或是不存在.概率数据结构能够提供一种基于内存的,快速的查找出一种可能而 ...
- Bloom Filter(布隆过滤器)的概念和原理
Bloom filter 适用范围:可以用来实现数据字典,进行数据的判重,或者集合求交集 基本原理及要点: 对于原理来说很简单,位数组+k个独立hash函数.将hash函数对应的值的位数组置1,查找时 ...
- Bloom Filter(布隆过滤器)的概念和原理(转)
Bloom filter 适用范围:可以用来实现数据字典,进行数据的判重,或者集合求交集 基本原理及要点: 对于原理来说很简单,位数组+k个独立hash函数.将hash函数对应的值的位数组置1,查找时 ...
- Hbase-之Bloom Filter布隆过滤器 hbase请求交互
Hbase-之Bloom Filter布隆过滤器&Hbase 1 BloomFilter是什么? 布隆过滤器,以它的创始人Burton Howard Bloom的名字命名,首先明确一个点,它只 ...
最新文章
- mysql连接hang住问题分析
- QDir::toNativeSeparators的使用
- 剑指offer:调整数组顺序使奇数位于偶数前面
- python网站开发linux_使用Python编写Linux系统守护进程实例
- c语言第七周答案,2017-mooc-C语言-第七周-答案
- CSAPP--整数的表示
- js解决客户端与服务器时间不一致的问题
- STL_算法_元素计数(count、count_if)
- 类的静态成员函数带来了什么好处,应该在什么时候使用?
- 【转】文件各种上传,离不开的表单
- SpringBoot--自动装配之Import注解以及源码分析
- echarts5.0 动态柱状图 不用调接口 不用jQuery舒适应用
- Maple 热工计算
- python抛出异常 后如何接住_如何在try中捕获异常后继续循环。。。例外
- [转载]美国夫妻生活如何在钱上更亲密
- 大学计算机组织部面试问题及答案,组织部面试问题及答案(30页)-原创力文档...
- LiveChart样式参数介绍
- 2019年风险投资人 ( VCPE ) 汇总
- slam入门——十四讲笔记(一)
- Windows 10 启用telnet client功能
热门文章
- 微信公众号/微信小程序获取用户信息以及推送微信模版消息_MQ
- Pycharm 常用快捷键大全【快查字典版】
- 【图像处理】图形图像中术语
- A*算法项目实践之一:栅格法的使用与障碍物栅格的生成
- html加入图片如何自动平铺,css怎么让图片平铺?
- 1688.item_search_img按图搜索1688商品(拍立淘)API的调用参数和实例
- 电脑双核CPU具体是什么意思?
- elastic-job VS xxl-job
- 阿里云域名解析网络和服务架构设计总概览(一)
- Vue与Angular以及React的区别