学习视频:小徐先生的编程世界:布隆过滤器实现
-
要解决的问题:海量数据中的数据去重
-
常规思路:维护一个set存储所有遍历过的数据,遍历数据时先判断是否在集合中,如果是则直接忽略;如果不是则添加到集合中。
成本损耗问题严重,假设一个数据占16byte,10亿条数据就是16GB,对于单机来说内存压力极大。
-
Bitmap
使用一个bit表示一个url是否存在在集合中,由16byte压缩至1bit,花费的空间仅为原方案的1/128。
-
如何建立一个bit位和一个url之间的关系?
-
方案一:单哈希散列
假设bitmap的长度为m,针对每个url取hash值,再对hash值对m取模,得到其对应bit位索引
但有哈希碰撞问题。
-
方案二:多哈希散列
增加hash函数的个数位k个,一个url对应的bit位就是k个。当判定所有hash映射的bit位都为1是,则判定为当前url存在。此时存在误判问题:
- 当一条数据被判定为存在时,实际数据可能不存在。因为hash的唯一性,当数据之前被添加时,对应的bit位都一定被置为1
- 当一条数据不存在时,实际数据一定不存在,可能是其他数据将其置为1,但其概率值可以被接受。
-
-
Bloom Filter优缺点总结
- 优点:
- 节省空间,利用k个hash函数进行映射后,bitmap的长度可以进一步降低。
- 查询的时间复杂度为O(1)
- 缺点:
- 对于不存在的数据可能会被误判为存在
- 无法实现数据删除:一个bit位可能被多个输入数据使用,因此删除想要删除的数据时可能影响其他数据的存在判定性。最终bitmap使用越久,被置为1的bit位越多,发生误判的概率越高。
- 在极端场景下,所有bit位都被置为1,则针对所有不存在的数据的误判概率位100%。
- 优点:
-
数据删除困难解决方案:
-
离线数据归档
根据时间线删除部分无用数据时,全量地离线构建在某个时间点以后的所有数据,构建完成后再将老的bitmap替换为新的bitmap。
布隆过滤器要对数据库形成一个保护,避免数据库的并发量过大。
-
使用场景一:
数据库或数据仓库假设保存了全量数据。由于布隆过滤器存在假阳性问题,当布隆过滤器判定数据存在时,去数据库再进行确认,否则直接返回不存在。
-
-
渐进式迁移
监控布隆过滤器(记作old)的误判率,当误判率达到一个阈值后,线上准备一个新的容量相同的bitmap(记作new),每次计算hash后,先去new中查找对应的数据是否存在:
- 如果存在,则表示数据真的存在,直接返回
- 如果不存在,再去old中去查找对应的bit位是否都为1,如果是,则将全部对应的bit位都写入new中
- 如果在old中也不存在,则数据真的不存在,返回
同时监控old的使用率,如果old的使用率低于一定的阈值后,将迁移流程关闭,把新的bitmap作为正式的布隆过滤器使用。
将离线很重的更新操作打散,提高了整体性能和系统的平稳程度
-
布谷鸟哈希
-