布隆过滤器
什么是布隆过滤器?
布隆过滤器是由一个长度为m比特的位数组与k个hash函数组成的数据结构。比特数组均初始化为0,所有hash函数都可以分别把输入数据尽量均匀的散列。
当插入一个元素时,将其数据通过k个hash函数转换成k个hash值,这k个hash值将作为比特数组的下标,并将数组中的对应下标置为1.
当查询一个元素时,同样会将其数据通过k个hash函数转换成k个hash值(数组下标),查询数组中对应下标的值,如果有一个下标的值为0表明该元素一定不在集合中,如果全部下标的值为1,表明该元素可能在该集合中,因为可能某个或者多个下标的值为1是收到其他元素的影响,这就是所谓的假阳性。
无法删除一个元素,因为这个元素对应的下标可能是好几个元素共享的,会导致其他数据被删除。
下图示出一个m=18, k=3的布隆过滤器示例。集合中的 x、y、z 三个元素通过 3 个不同的哈希函数散列到位数组中。当查询元素 w 时,因为有一个比特为 0,因此 w 不在该集合中。
降低重复率的方式就是增加hash函数的数量,如果需要很低的重复率,则需要很多数量的hash函数,很大程度上降低系统的效率,所以设置一个适当的重复率很关键。
优点
用比特数组表示,不用存储数据本身,对空间的节省相比于传统方式占据绝对的优势。
时间效率很高,无论是插入还是查询,只需要简单的经过哈希函数转换,时间复杂度均为O(k)。
缺点
存在假阳性的概率,准确率要求高的场景不太适用。
只能插入和查询,不能删除了元素。
应用场景
布隆过滤器的用途很多,但是主要的作用就是去重,这里列举几个使用场景。
抖音推荐功能
读者朋友们应该没人没刷过抖音吧,每次刷的时候抖音给你的视频有重复的吗?他是如何保证推荐的内容不重复的呢?
最容易想到的就是抖音会记录用户的历史观看记录,然后从历史记录中排除。这是一种解决办法,但是性能呢?不用多说了,有点常识的都知道这不可能。
解决这种重复的问题,布隆过滤器有着绝对的优势,能够很轻松的解决。
防止缓存穿透
缓存穿透是指查询一条数据库和缓存都没有的一条数据,就会一直查询数据库,对数据库的访问压力会一直增大。
布隆过滤器在解决缓存穿透的问题效果也是很好,这里不再细说,后续文章会写。