目录
场景
场景一:原本有10亿个号码,现在又来了10万个号码,要快速准确判断这10万个号码是否在10亿个号码库中?
解决一:将10亿个号码存入数据库中进行数据库查询;
解决二:将十亿个号码存入内存中,比如Redis缓存中,这里我们算一下占用内存大小:10亿*8字节=8GB,通过内存查询,准确性和速度都有了,但是大约8gb的内存空间,挺浪费内存空间的;
场景二:接触过爬虫的,应该有这么一个需求,需要爬虫的网站千千万万,对于一个新的网站url,我们如何判断这个url我们是否已经爬过了?
布隆过滤器的介绍
布隆过滤器:一种数据结构,是由一串很长的二进制向量组成,可以将其看成一个二进制数组。既然是二进制,那么里面存放的不是0,就是1,但是初始默认值都是0
添加数据
我们可以将布隆过滤器看成一个容器,那么如何向布隆过滤器中添加一个数据呢?
1.首先当要向布隆过滤器中添加一个元素key时,我们通过多个hash函数,算出一个值,然后将这个值所在的方格置为1(当这个位置没有添加元素的时候,也就是位置为0的时候)
比如,下图hash1(key)=1,那么在第2个格子将0变为1(数组是从0开始计数的),hash2(key)=7,那么将第8个格子置位1,依次类推;
判断该位置数据是否存在?
知道了如何向布隆过滤器中添加一个数据,那么新来一个数据,如何判断是否已经存在于这个布隆过滤器中呢?
1.首先将这个新的数据通过自定义的几个哈希函数计算出位置值,看布隆过滤器对应的位置是否都为1,如果不为1,说明该数据一定没有存在于布隆过滤器中
2.但是可能出现不同的数据经过hash计算得到一样的值,所以说可能会出现哈希冲突的情况——>存在位置上是不一样的数据将布隆过滤器位置置为1
结论:
布隆过滤器可以判断数据一定不存在(位置为0),但是不能判断数据是否一定存在(多个数据置1)
优点:二进制组成的数组首先占空间较少(不是0就是1),并且查询速度较快(下标)
缺点:数据量越大,误判率越高,毕竟存在不同数据将位置置为1的情况(哈希冲突)——>判断数据存在错误率还是有的,但是判断数据不存在还是非常nice
Redis实现布隆过滤器
bitmaps——>它本身不是一种数据结构,只是一个定义在String类型上面向字节的一个集合
例子:
我们知道计算机是以二进制位作为底层存储的基础单位,一个字节等于8位。
比如“big”字符串是由三个字符(一字符一字节,big也就是3字节)组成的,这三个字符对应的ASCII码分为是98、105、103,对应的二进制存储如下:
在Redis中,Bitmaps 提供了一套命令用来操作类似上面字符串中的每一个位
1.将set的键值对利用Bitmaps的命令进行修改
设置k1为big后,setbit k1 7 1——>将k1对应值big中的第7位修改为1——>变成cig了
我们知道"b"的二进制表示为0110 0010,我们将第7位(从0开始)设置为1,那0110 0011 表示的就是字符“c”,所以最后的字符 “big”变成了“cig”;
2.获取键值上某位的值
getbit key offset
cig三个字符,也就是三个字节,24位