本篇是布隆过滤器专栏的第三篇,前面两篇地址(布隆过滤器2——改进结构的布隆过滤器)和(布隆过滤器——开发必会知识点)
一.哈希函数介绍
哈希函数在数据结构中很常见,实际数据结构中利用非常多,在布隆过滤器中有两种功能的哈希函数
-
用作地址映射的哈希函数: 在布隆过滤器的位向量中,哈希函数将集合元素映射后作为位向量地址存储到位向量的某些位置上。
-
用作元素指纹的哈希函数: 当集合元素的数据类型和长度各不相同时,哈希函数可以将这些不同的数据统一映射为相同长度的二进制串(开发中常见的是使用MD5函数 ——无论输入的数据长度如何,都会得到长度相同的输出),也就是元素的指纹。这样一来,不论元素的实际数据类型如何,布隆过滤器都可以以统一的方式处理并存储这些元素。再通过这个元素进行地址映射哈希得到相应的存储地址。
哈希冲突:
哈希冲突是指在使用哈希表存储数据时,两个或多个不同的键被哈希函数映射到同一个位置的情况。
哈希表:
采用哈希技术将记录存储在一块连续的存储空间中形成的“表”。
二.bloomier过滤器(通过查询直接返回值)
本人简单理解(可能存在一些小错误),于标准BF区别
1.哈希函数使用了避免哈希冲突的方式如常见的开放地址法使得不存在哈希碰撞
2.为了保证查询,在实际存储的位置上加了该元素值哈希的解码,以便于比较所有可能的位置中是真的位于哪一位
3.因为事先已经通过算法来得到可能的值的位置所以它不能支持删除或者更更新插入
4.与标准过滤器不同的是bloomier过滤器不再是位向量而是真的存储值的数组。所以与纯粹的判断元素是否在集合中的比较意义不大。而最重要的是它可以直接快速的通过一个关键词找到它的value。这就特别适合在一些高速查询的系统中作为数据能够直接返回值。
5.举例理解
插入元素:
- 对于每个元素,计算哈希函数并通过贪心算法(即之间所说的避免哈希冲突的算法)得到所有可能的映射位置。
元素 | 可能映射位置(哈希函数示例) |
---|---|
apple | 3, 8 |
banana | 0, 5 |
orange | 1, 6 |
grape | 2, 7 |
pear | 4, 9 |
选择映射位置:
- 选择未被占用的映射位置,例如:
元素 | 选择的映射位置 |
---|---|
apple | 3 |
banana | 0 |
orange | 1 |
grape | 2 |
pear | 4 |
假设我们要查询元素 "banana" 是否存在于Bloomier过滤器中:
-
计算可能映射位置:计算 "banana" 的可能映射位置,即 0 和 5。
-
检索过滤器值:从Bloomier过滤器中读取存储的过滤器值:
可能映射位置 过滤器值(存储值) 0 Hash(banana) 5 - -
验证元素存在:
- 对读取到的过滤器值应用额外的哈希函数,得到验证结果。
- 如果验证结果与预期的额外哈希值匹配,则确认元素存在于集合中。
三.布谷鸟过滤器(综合性能最好)
3.1布谷鸟哈希
布谷鸟哈希核心在于哈希替换——布谷鸟哈希中每一个元素中有两个桶,分别使用了两种哈希函数存储两个下标,其中一个是主位置,另一个则是备用的位置。当主位置发生哈希冲突时,就会将元素存储到备用位置中,而如果备用位置也产生了冲突,就会将原有冲突的元素剔除,让其重复执行之前的流程,直到次数达到阈值时,才认为哈希表已满,进行 rehash。
3.2布谷鸟过滤器
布谷鸟过滤器存储的是元素的指纹,它是针对于布谷鸟哈希函数的改进,布谷鸟过滤器每一位能够存储多个元素的指纹,元素通过MD5的哈希函数得到指纹,而后通过异或的方式得的另一个指纹,这两个指纹可以互相得到(异或)
布谷鸟过滤器本质上是将一维的哈希表改进成二维的哈希表实现了空间利用率的提高,同样的与计数器布隆过滤器一样的原理,它也可以判断元素的个数。通过查询得到两个位置之后可以知道它里面存储的值的数量是多少。但是由于它是通过哈希得到的结果无法反推回原先的值,所以无法得到具体存储的value。
3.3应用和优势
- 空间效率:相对于直接存储所有数据,布谷鸟过滤器通常可以以更少的空间存储数据。
- 查询效率:查询效率较高,尤其适合于大规模数据集合中的成员查询。
- 误报率降低:通过多项式插值技术,可以显著降低误报率,提高准确性。