从开始编程到现在经常的遇到存在问题,就是一个元素是否再某个容器当中,比如用户名是否存在,链接是否重复等等,那么基于判定存在的场景,我们基本上可以考虑到的方法:
1、线性查找
2、树形查找(红黑树,AVL)
3、哈希表
上面都可以解决这个问题,但是面对海量的数据,上面的解决方案难免遇到 查询时间长,存储占用大的问题,那么我们来聊一个看似不靠谱的方法,布隆过滤器。
原理
为啥说他不靠谱,原因很简单,布隆过滤器查询实际上是按照指定的数据结构对数据进行记录,然后针对记录进行查询的方法,他可以确定的告诉你这个元素不在布隆过滤器的容器当中,但是不能确定他在布隆过滤器当中,呐,说到这里,是不是有的小伙伴已经感觉迷糊了,不能确定在,那要他干啥,对,用它判断不在就可以了,具体的实现原理如下:
首先定义一个n位的数组,数组每个元素默认为0,和n个哈希算法,
这里假使数组24位,hash算法3个
插入数据的时候,分别使用三种算法,对插入的数据进行计算,将计算的结果对应的奥数组相同的位数上,将该位值改成1
值1 hash算法1的值是2,所以2号索引的元素值该位1
值1 hash算法2的值是4,所以4号索引的元素值该位1
值1 hash算法3的值是6,所以6号索引的元素值该位1
这样,如果查询值2是否再hash列表当中,那么直接对值2进行三次hash算法,然后进行映射,如果发现映射的索引位上的元素有不为1的,那么肯定不存在。
同理,如果都为1,可能是存在,但是不是也有肯能是其他数据将索引为修改成1的,所以可能存在,也可能不存在。
那这就是布隆过滤器的原理,通过原理我们自然可以总结出:
1、节省空间,通过上面的案例就可以看出,布隆过滤器不需要存储数据本身,只需要存储数据对应hash比特位
2、时间复杂度低,有几个hash函数,时间复杂度就是O几,比如上面的案例就是O(n)
3、判断的准确度取决于hash的长度
4、由于不确定应存在,所以无法删除元素(在不在都不知道,咋删除,没得删)
Redis布隆过滤器
最后,给大家附带上一个成熟的布隆使用方法,使用redis布隆过滤器,当然,各位大佬也可以结合自己使用的后端语言的api使用redis 布隆过滤器。
安装redisbloom过滤器插件
插件地址:
https://github.com/RedisBloom/RedisBloom
下载解压文件:
unzip RedisBloom-master.zip
拷贝插件到redis的bin目录下
cp /opt/redisbloom.so /usr/local/redis/bin/redisbloom.so
修改redis的配置文件:
loadmodule /usr/local/redis/bin/redisbloom.so
从其服务:
sudo /etc/init.d/redis-server restart
#测试是否安装成功
127.0.0.1:6379> bf.add key1 value1
常用的api附上
| 方法 | 描述 |
|---|---|
| bf.add | 添加元素到布隆过滤器,也是key/value结构 |
| bf.exists | 判断某个元素是否在布隆过滤器当中,参数和add一样,也是指定key和value判断。 |
| bf.madd | 同时添加多个元素到布隆过滤器。这里要注意是一键多值哦,bf.madd key1 value1 value2 value3 |
| bf.mexists | 同时判断多个元素是否存在于布隆过滤器中。同样是一键多值,bf.mexistskey1 value1 value2 value3 |
最后还是欢迎各位大佬多多指点。