Redis过滤器的实现方式(布隆过滤器 布谷鸟过滤器)

前言

昨天聊到了 Redis 的位图, 那今天就顺带聊聊位图的最常见场景之一: 大数据下去重过滤功能.

正文

最常见的例子: 十亿邮箱去重. 无论用Redis哪种格式, 内存的消耗都是极大的. HyperLogLog 的 0.81%的错误率, 在这种场景又显得太高.

所以就有了布隆过滤器.
布隆过滤器原理是通过多个 hash 函数, 将结果对应的位设为1, 所以它能做到 100%的去重. 虽然会误判, 但是在合理的设计的前提下, 误判率是可以接受的.
但布隆过滤器也不是完美无缺的.
首先它的查询性能相对较弱, 它是用 hash 函数在位图上不同的点跳跃探测, 很难利用 cpu 缓存.
第二它不支持删除, 假如邮箱a 的 hash 结果分别是 1 3 7, 邮箱 b 的结果是 2 6 7. 那么在删除邮箱a 的结果之后, 邮箱 b 也会被重新认为是不存在, 因为第 7 位的值是 0. 这一点布隆过滤器也很无奈.当位图拥挤到一定程度, 只能选择重建整个位图.

聊这么多, 还是得说下, redis 原生并不支持布隆过滤器, 需要自己编译加载
https://oss.redislabs.com/redisbloom/
喜欢摸索技术的也可以用自己喜欢的语言实现, 或者使用 lua 脚本.

虽然布隆过滤器不支持删除, 但是有升级版的布隆过滤器: Counting Bloom Filter. 它的原理就是把位图的位 升级为计数器(Counter). 添加元素, 就给对应的Counter分别+1; 删除元素, 就给对应的Counter分别减一. 用多出几倍存储空间的代价, 来实现删除功能. 虽然实现了功能, 但是不够完美.

于是布谷鸟过滤器(Cuckoo filter)华丽降世了.
首先要说明布谷鸟过滤器并不是使用位图实现的, 而是一维数组. 它所存储的是数据的指纹(fingerprint).
布谷鸟过滤器使用两个 hash 算法将新来的元素映射到数组的两个位置. 如果两个位置中有一个位置位空, 那么就可以将元素直接放进去. 但是如果这两个位置都满了, 它就会随机踢走一个, 然后自己霸占了这个位置.
正如布谷鸟那样, 把蛋下到其它鸟的窝里. 这也是得名的由来. 但它并不是像布谷鸟那样, 管杀不管埋, 还会为这个被踢走的数据, 找一个新家.
这里看一下它的公式, Cuckoo filter中只采用两个哈希映射函数 H1 和 H2,H3用于计算数据的 fingerprint. 他们的关系如下

H3(key) = key’s fingerprint = hash(key)
H1(key) = hash1(key)
H2(key) = H1(key) ^ H1(key’s fingerprint) // 异或

从上面的公式中可以看出,当我们知道 fingerprint 和 H1(key),就可以直接算出 H2(key)。同样如果我们知道 H2(key) 和 fpfingerprint 也可以直接算出H1(key) ---- 对偶性.
通过 fingerprint 和当前位置, 算出对应的另一个巢, 然后安放这个可怜的数据. 如果另一个巢仍然有数据, 那就为受害者继续寻找下一个巢.
但也有问题, 假如数组太过拥挤, 踢了几十次仍然没有找到空缺的巢, 那就需要为数组扩容了.
不过原生的布谷鸟过滤器空间利用率并不高, 大约 50%. 改良的方案之一是增加 hash 函数, 让每个元素不止有两个巢, 这样可以大大降低碰撞的概率, 将空间利用率提高到 95% 左右.
还有个方案是给每个位置上挂多个巢, 这样不会马上就挤来挤去. 也能大大降低碰撞概率, 空间利用率虽然比第一种改良方案稍低(约为 85%), 但cpu 缓存的利用率会提高不少.
甚至还可以将两种方案结合, 据说空间利用率高达99%. 了不起的数字.
要删除也很简单, 找到对应位置的指纹信息删除即可.
但布谷鸟过滤器有一个明显的弱点, 无法对同一个数据连续插入!
刚才也说到了, 假如数组太拥挤, 碰撞多次仍然未找到空缺的巢, 那就需要扩容了. 那么连续插入同一个数据, 马上就触发了扩容.
而且因为存储的只是一个字节的指纹信息, 也很难判断插入的数据和位置上的数据, 是不是同一个数据. 算法论文上也有说明, 支持删除, 不支持同一个数据多次插入. 要确保每一个元素不会被插入多次(kb+1). k 是指 hash 函数的个数 2,b是指单个位置上的座位数. 也就是说原生布谷鸟过滤器, 不能超过 3.

附上 Redis 模块地址:
https://github.com/kristoff-it/redis-cuckoofilter
布谷鸟过滤器论文:
https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf

end.

你可能感兴趣的:(redis)