JAVA-缓存-布隆过滤器

布隆过滤器

Data structures are nothing different. They are like the bookshelvesof your application where you can organize your data. Different datastructures will give you different facility and benefits. To properlyuse the power and accessibility of the data structures you need toknow the trade-offs of using one.

什么是布隆过滤器:

本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构,特点是可以高效的插入和查询。它可以告诉你 “哪些数据是一定不存在的,哪些数据是可能存在的” 。
相比传统的list set map等数据结构,布隆过滤器更高效,占用空间更少。缺点是:概率性,不是确切的。

实现原理:

hashMap问题:

通常判断某个元素是否存在,会使用HashMap,确实可以将值映射到 HashMap 的 Key,然后可以在 O(1) 的时间复杂度内返回结果,效率奇高。但是 HashMap 的实现也有缺点,例如存储容量占比高,考虑到负载因子的存在,通常空间是不能被用满的,而一旦你的值很多例如上亿的时候,那 HashMap 占据的内存大小就变得很可观了。

布隆过滤器数据结构:

布隆过滤器是一个bit向量或者说bit数组:
在这里插入图片描述
如果我们想要把一个值存放到布隆过滤器中,需要使用多个哈希函数生成多个哈希值,并对每个哈希值执行的bit位置置为1.例如:baidu通过哈希函数得到的哈希值是 1 4 7
在这里插入图片描述
如果再存放一个tencent 3 4 8 :
在这里插入图片描述
值得注意的是,4 这个 bit 位由于两个值的哈希函数都返回了这个 bit 位,因此它被覆盖了。现在我们如果想查询 “dianping” 这个值是否存在,哈希函数返回了 1、5、8三个值,结果我们发现 5 这个 bit 位上的值为 0,说明没有任何一个值映射到这个 bit 位上,因此我们可以很确定地说 “dianping” 这个值不存在。而当我们需要查询 “baidu” 这个值是否存在的话,那么哈希函数必然会返回 1、4、7,然后我们检查发现这三个 bit 位上的值均为 1,那么我们可以说 “baidu” 存在了么?答案是不可以,只能是 “baidu” 这个值可能存在。

这是为什么呢?答案跟简单,因为随着增加的值越来越多,被置为 1 的 bit 位也会越来越多,这样某个值 “taobao” 即使没有被存储过,但是万一哈希函数返回的三个 bit 位都被其他值置位了 1 ,那么程序还是会判断 “taobao” 这个值存在

如何选择布隆过滤器的长度和使用哈希函数的个数:
  • 如果布隆过滤器过小:
    如果布隆过滤器过小,会出现使用时间越长,布隆过滤器的各个位置都置为1.布隆过滤器的误报率越来越高,以至于最后失效。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。
  • 哈希函数个数:
    如果哈希函数的个数过大,很快布隆过滤器的各个位置置为1的速率也越快,误报率提升越来越快。
    如果哈希函数的个数过小,误报率也会变高。

布隆过滤器长度和哈希函数个数:

在这里插入图片描述

其中:
m为布隆过滤器长度,n为插入元素个数,p为误报率。
k为哈希函数的个数。
大Value拆分

Redis 因其支持 setbit 和 getbit 操作,且纯内存性能高等特点,因此天然就可以作为布隆过滤器来使用。 但是布隆过滤器的不当使用极易产生大 Value,增加 Redis 阻塞风险,因此生成环境中建议对体积庞大的布隆过滤器进行拆分。
拆分的形式方法多种多样,但是本质是不要将 Hash(Key) 之后的请求分散在多个节点的多个小 bitmap 上,而是应该拆分成多个小 bitmap 之后,对一个 Key 的所有哈希函数都落在这一个小 bitmap 上。

bloom fiter 是否支持删除:

  • 传统的bloom fiter 并不支持删除功能,原因:

比如要删除集合中的成员 dantezhao,那么就会先用 k 个哈希函数对其计算,因为 dantezhao
已经是集合成员,那么在位数组的对应位置一定是 1,我们如要要删除这个成员 dantezhao,就需要把计算出来的所有位置上的 1 置为0,即将 5 和 16 两位置为 0 即可。
在这里插入图片描述
问题来了!现在,先假设 yyj 本身是属于集合的元素,如果需要查询 yyj 是否在集合中,通过哈希函数计算后,我们会去判断第 16 和 第 26 位是否为 1, 这时候就得到了第 16 位为 0 的结果,即 yyj 不属于集合。 显然这里是误判的。

  • Counting bloom fiter
为解决删除问题,Counting bloom fiter 出现了。
Counting bloom fiter 将标准的bloom fiter数组的每一位都拓展为一个小的计数器(counter)。
在插入元素时,给对应的k个counter的值分别 +1 ,删除元素时在对应的k的位置上进行 -1.但是
counting bloom fiter 通过多占用几倍的存储空间为代价,增加了删除操作。

在这里插入图片描述

CBF 和 BF 的一个主要的不同就是 CBF 用一个 Counter 取代了 BF 中的一位,那么 Counter 到底取多大
比较合适呢?这里就要考虑到空间利用率的问题了,从使用的角度来看,当然是越大越好,因为 Counter 越
大就能表示越多的信息。但是越大的 Counter 就意味着更多的资源占用,而且在很多时候会造成极大的空间
浪费。

因此,我们在选择 Counter 的时候,可以看 Counter 取值的范围多小就可以满足需求。大多数应用程序选择
4位,即16即可。

counting bloom fiter 虽说解决了bloom fiter 的不能删除元素的问题,但是自身仍有不少的缺陷有待完善,比如 Counter 的引入就会带来很大的资源浪费,counting bloom fiter
的 FP 还有很大可以降低的空间, 因此在实际的使用场景中会有很多 CBF 的升级版。

比如 SBF(Spectral Bloom Filter)在 counting bloom fiter 的基础上提出了元素出现频率查询的概念,将CBF的应用扩展到了
multi-set 的领域;dlCBF(d-Left Counting Bloom Filter)利用 d-left hashing
的方法存储 fingerprint,解决哈希表的负载平衡问题;ACBF(Accurate Counting Bloom Filter)通过
offset indexing 的方式将 Counter 数组划分成多个层级,来降低误判率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值