引子

“之前坑是你留的吧?!怎样不过来填上,我在坑里还没出来呢!”

非常抱愧啊,之前坑留的有点多。就请你给我多一点点时刻,再多一点点温柔,不要让我如此难过。

布隆过滤器是个啥!

不用忧虑,我说过,挖的+ } O & i f坑跪着我也会填上的。今日就填一个Bloom Filter的坑。这是之前一期中《redis系列之——缓存穿透、缓存击穿、缓存雪崩》留下的。

今日我们就哔哔一下布隆过滤器的那些事!

常识布景

详细的定义请自行问某度,就不哔哔了。

相关布景能够回忆一下我之前的文章《redis系列之——缓存穿透、缓存击穿、缓存雪崩》。

Bloom Filter是一个占用空间很小、功率很高的随机数据结构,它由一个bit数组和一i ] T 0组Hash算法构成。主要作( & D . 6用是:判别一个元素是否在一个调集中,具有查询功率很高,节约空间等长处;缺点是有必定的误识别率(false-positi& Y } Mve,假阳性),可能会把不– k o c l是调集内的元素判定为存在于调集内,可是概率相当小,在大部分的出产环境中是能够接受的;关于假阳性问题,请记住一句话Bloom Filter说这条数据存在,这条数据不必定存在;可是Bloom Filter说这条数据不存在,* Q ! d f R K =这条数据必定不存在。

原理也比较简单,听起来不像人话。S调集中有n个元M T W ` w . – Z 1素,运用k个哈希函数,将S中的每个元素映射到一c ~ p j N )个长度为% x S . E M _m的位(bit)数组B中8 0 B j Q不同的方位上,这些方位上的二进制数均置为1,假如待检测的元素经过这k个哈希函数的映射后,发; X =现其k个方位上的二进制数不全是n ] k : / z 21,那么这个元素必定不在调集S中5 } P P m _ 4,反之,该元素可能是S中的某一个元素。

简单实例

运用一个比如,; 7 G将上面这一段翻译成人话:

假如,数据库中有100条订单数据,id分* + b s _ S : 9别从1到100,现在用户经过id查询订单数据,为了避免缓存穿透,我们需求提前做一个bloom filter(一个自定义的bit数组长度为1000,并自定义一个hash算法),将数据库中的一切ik ; z a u ! ud提前经过hash算法核算后,放到bit数组中;当用户的请求到达controller层中,先到这个数组中查询这个id是否$ 0 * V存在,假如存在,在让请求往下走,拜访redis或mysql;假如不存在则直接返回。

那么这个如何将这100个id经过h? – G S ] dash算法存到bit数组中呢?

布隆过滤器是个啥!

上面这个图便是将订单Id经过hash函数放入bit数据之前的情况。这里需求M X m注意hash函数的要求,一起bit数组长度暂定为1000。然后经过下图,将每一个订单id,经过hash函数的核算,得到一个0-999之间的一个数字;比如id=1经过hash函数核算的到3,就将bit数组中索引为3的方位的值由0变成1,依次类推T ) : =处理剩余的一切id,这样就得到一个id处理后的bit数组。

布隆过滤器是个啥!

当用户经过id查询时订单时,相同将id经过这个hash函数生成bit数组的下标l n y 6 : /,假如这边下标对应的bit元素的值为1,则表明数据存在,能够继续查询redis或mysql;假如这E _ j k ?个下标对应的bit元素的值为0,表明这个数据不存在,直接返回。

从上W : { ? U ^ ) n %面能够看出,存储100个id运用的内存便是1000bit,比直接存储id时占9 o b )用的内存空间小很多。

一起,这种判别机制也大大提高了查询功率。

存在的问题

上面的事例,假2 7 |定id=110的数据经过hash函数核算的值也是3,那么当用户查询这条数据时,数据库不存在这条数据,可是bl4 * M $ Ioom filter查询后显现数据存在,一切也会查询redis和mysql。这便是hash碰撞导致的假阳性,所以说Bloom Filter说这条数据存在,这条数据不必定存在;E G A r b 0 N可是Bloom Filter说这条数据不存在,这条数据必定不存L F H ~ } D 在。: R A 8 A o # d q

如何解决这个问题呢?4 | v x b (能够经过添加hash函数的个数和添加bit数组的长度来解决。

添加hash函数,如下图所示,每一个id都经过两个hash函数核算,得到两个索引方I j 1 + d t &位,经过两个方位的值是不是1来确定该数据是否存在,能够下降hash碰撞概率。

一起添加bit数组长度,能够增大hash函数生成的数N P c J N x据的规模,也能够下降hash碰撞,削减假阳性概率a 1 z e t h

从上面能够看出,Bloom Filter不@ { X K [ 0 h l +适合那些“零错误”的运用场合z ? 7 R。而在能忍受低错误率的运用场合下,Bloom Filter经过极少的错误W $ X y c r换取了存储空间的极大节约。

布隆过滤器是个啥!

**那么,关于不同的场景$ _ ] s,在可接受的假阳性率规模内,运用几个hash函数及bit数组应该设置为多长便是可优化的点。**详细的算法的优化就不是我的才能V / J M r . : k规模内的工作了,只能送我们到这里了。

布隆过滤器是个啥!

最终简单介绍一下完成。现在bloom filter已经有相应完成的开源类库,如Google的Guava类库,Twitter的Algebird类库,和ScalaNLP breeze等: ^ N等。也能V 9 ( N够基于Redis自带的Bitmaps作为底层的bit数组自行设计bloom filter;一起redis 在 4.0 的e t g l E p P版本中加入了 moR k W G B p hdule 功能,布隆过滤器能够经过 module 的方式添加到 redis 中运用。

重视大众号,输入关键字”java-summary“,能够获得源码。

完成,收工!!

布隆过滤器是个啥!

传播常识,共享价值】,感. z X ; N [ L 1谢小伙伴们的重视和支持,我是【诸葛小猿】,一个徘徊中斗争的互联网民工。

布隆过滤器是个啥!