引出布隆过滤器
现在有50亿个电话号码,如何快速且准确的判断10万个电话号码是否包含在其中?
方案一,假设50亿个电话号码都存储在数据库中,通过in的操作进行查询,会占用大量的数据库资源并且满足不了快速。
方案二,将50亿个电话号码都存储在内存当中,假设一个电话号码占用8个字节,50 * 8 约等于40GB,内存占用太大。
方案三,hyperloglog,保证不了准确率,官网给出的误差率是0.81%。
在实际的生产环境中,类似上述问题的应用的场景也非常多。
缓存穿透场景。
网络爬虫重复url检测。
...。
由此引出布隆过滤器
布隆过滤器基本原理
1970年由伯顿.布隆提出,用很小的空间,用来解决上述问题,判断一个小数据集是否存在于一个大数据集中。
实现原理
一个很长的二进制向量和若干个哈希函数。
以136xxxx9871为例:函数f1计算出的值%向量长度=index,并将对应的index值设置为1,上述操作f2、f3...f8依次执行。
![](https://i-blog.csdnimg.cn/blog_migrate/b97feda67bbb6610434f025f1f9ec9ce.jpeg)
初始化布隆过滤器
将大数据集的每一个元素执行上述136xxxx9871例子的执行过程。例如:50亿个电话号码,就需要执行50亿次。
使用布隆过滤器
136xxxx9872为例,经过f1、f2、f3...f8%向量长度,并且判断这8个下标是否都为1,如果都为1则可以判断出,136xxxx9872一定在这50亿数据当中。
也能会出现明明不在50亿数据当中,被误判的情况。误判的概率与向量的长度有关,长度越长错误率越低,长度越短错误率越高。
redis实现布隆过滤器
基于redis的位图(bitmap)进行实现。这里仅给出思路。
redis单机版
优点,实现相对简单。
缺点,并发量上会受到限制,同时会受限于string 512M的限制。
redis-cluster版
基本思路,是将一个大的布隆过滤器拆分成多个小的布隆过滤器。先对key进行一次hash来确定对应的子布隆过滤器。
优点,可以大大提高并发量,不受string 512M限制。
缺点,实现相对复杂。