牛哄哄的布隆过滤器,有什么用?( 二 )


如下图:
牛哄哄的布隆过滤器,有什么用?
文章图片
跟初始化的过程有点类似 , 当查询一件商品的缓存信息时 , 我们首先要判断这件商品是否存在:
通过三个哈希函数对商品id计算哈希值然后 , 在布隆数组中查找访问对应的位值 , 0或1判断 , 三个值中 , 只要有一个不是1 , 那么我们认为数据是不存在的 。注意:布隆过滤器只能精确判断数据不存在情况 , 对于存在我们只能说是可能 , 因为存在Hash冲突情况 , 当然这个概率非常低 。
如何减少布隆过滤器的误判?
①增加二进制位数组的长度 。 这样经过hash后数据会更加的离散化 , 出现冲突的概率会大大降低 。
②增加Hash的次数 , 变相的增加数据特征 , 特征越多 , 冲突的概率越小 。
布隆过滤器会不会很费内存?
带着疑问 , 我们来做个实验:假设有1千万个数据 , 我们需要记录其是否存在 。 存在的话标记1 , 不存在标记为0 。 技术选型 , 框架采用Redis的BitMap存储 。
数据初始化预热代码:
redisTemplate.executePipelined(newRedisCallback<Long>(){@Nullable@OverridepublicLongdoInRedis(RedisConnectionconnection)throwsDataAccessException{connection.openPipeline();for(intoffset=10000000;offset>=0;offset--){booleanvalue=https://pcff.toutiao.jxnews.com.cn/p/20210904/offset%2==0?true:false;connection.setBit(''bloom-filter-data-1''.getBytes(),offset,value);}connection.closePipeline();returnnull;}});System.out.println(''数据预热完成'');性能有点慢 , 我们也可以采用分组形式 , 10000个数一组 , 多批次提交 。
牛哄哄的布隆过滤器,有什么用?
文章图片
数据上传完了后 , 大小1.19M , 跟我们设想的一样 。
计算公式:10000000/8/1024/1024=1.19M
Java应用中 , 如何使用布隆过滤器?
Java语言的生态非常繁荣 , 提供了很多开箱即用的开源框架供我们使用 。 布隆过滤器也不例外 , Java中提供了一个Redisson的组件 , 它内置了布隆过滤器 。
首先引入依赖包:
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.11.1</version></dependency>代码示例:
/***@author*/@Testpublicvoidtest5(){Configconfig=newConfig();config.useSingleServer().setAddress(''redis://172.16.67.37:6379'');RedissonClientcient=Redisson.create(config);RBloomFilter<String>bloomFilter=cient.getBloomFilter(''test5-bloom-filter'');//初始化布隆过滤器 , 数组长度100W , 误判率1%bloomFilter.tryInit(1000000L,0.01);//添加数据bloomFilter.add(''Tom哥'');//判断是否存在System.out.println(bloomFilter.contains(''微观技术''));System.out.println(bloomFilter.contains(''Tom哥''));}运行结果:
false//肯定不存在true//可能存在 , 有1%的误判率注意:误判率设置过小 , 会产生更多次的Hash操作 , 降低系统的性能 。 通常我们的建议值是1% 。
布隆过滤器二进制数组 , 如何处理删除?
初始化后的布隆过滤器 , 可以直接拿来使用了 。 但是如果原始数据删除了怎么办?布隆过滤器二进制数组如何维护?
直接删除不行吗?还真不行!因为这里面有Hash冲突的可能 , 会导致误删 。
怎么办?
方案1:开发定时任务 , 每隔几个小时 , 自动创建一个新的布隆过滤器数组 , 替换老的 , 有点CopyOnWriteArrayList的味道 。 方案2:布隆过滤器增加一个等长的数组 , 存储计数器 , 主要解决冲突问题 , 每次删除时对应的计数器减一 , 如果结果为0 , 更新主数组的二进制值为0 。布隆过滤器的应用场景
如下:
本文重点介绍的 , 解决缓存穿透 。
网页爬虫对URL的去重 , 避免爬取相同的URL地址 。