You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
# 一、介绍
|
|
|
|
|
可以把布隆过滤器理解为一个不怎么精确的set结构。当布隆过滤器判定某个值存在时,这个值可能不存在;当判定某个值不存在时,那肯定不存在。误判率大约为1%左右。
|
|
|
|
|
# 二、使用方法及注意事项
|
|
|
|
|
| 命令 | 用途 |
|
|
|
|
|
| ---------- | ------------------------ |
|
|
|
|
|
| bf.add | 添加元素 |
|
|
|
|
|
| bf.exists | 判断元素是否存在 |
|
|
|
|
|
| bf.madd | 批量添加元素 |
|
|
|
|
|
| bf.mexists | 一次查询多个元素是否存在 |
|
|
|
|
|
|
|
|
|
|
![[Snipaste_2023-02-23_17-24-34 12.png]]
|
|
|
|
|
|
|
|
|
|
## 显示创建布隆过滤器
|
|
|
|
|
先说为什么需要显示创建,redis提供的默认设置错误率为0.01、预计放入的元素量为100,实际使用中我们的元素肯定不止100个,所以需要自定义创建,并且对于错误率的容忍度也不一样。
|
|
|
|
|
redis提供了bf.reserver命令,格式如下 bf.reserver key error_rate initial_size
|
|
|
|
|
error_rate(错误率,错误率越低需要的空间越大)
|
|
|
|
|
initial_size(预计放入的元素数量,当实际数量超出这个数值时,误判率会上升,所以需要提前设置一个较大的数值避免超出导致误判率升高)
|
|
|
|
|
![[Snipaste_2023-02-23_17-24-34 13.png]]
|
|
|
|
|
# 三、原理
|
|
|
|
|
布隆过滤器对应到Redis的数据结构里面就是一个大型的位数组和几个不一样的无偏hash函数。所谓无偏就是能够把元素的hash值算的比较均匀,让元素被hash映射到位数组中的位置比较随机。
|
|
|
|
|
![[Snipaste_2023-02-24_09-52-40.png]]
|
|
|
|
|
|
|
|
|
|
## 3.1 添加Key
|
|
|
|
|
会使用多个hash函数对Key进行Hash,算得一个整数索引值,然后对位数组长度进行取模得到一个下标,每个hash函数都会算的一个不同的下标。再把位数组的对应下标置为1,就完成了添加操作。
|
|
|
|
|
## 3.2 判断Key是否存在
|
|
|
|
|
和添加操作一样,先根据Hash计算下标,然后与位数组中这几个位置对比,是否为1,只要有一个为0,那么说明Key不存在。如果都是1,只能说明key可能存在,因为这些位置被置为1可能是因为其他key存在导致的。
|
|
|
|
|
自定义布隆的initial_size参数与位数组长度有关,如果位数组比较稀疏,判断正确的概率就会很大,如果位数组比较拥挤,判断正确的概率就会降低。
|
|
|
|
|
## 3.3 空间占用率估计
|
|
|
|
|
布隆有两个参数,预计元素的数量m,错误率f。公式根据这两个输入得到两个输出,第一个输出是位数组长度l,第二个是hash函数的最佳数量k
|
|
|
|
|
k=0.7*(l/n)
|
|
|
|
|
f=0.6185^(l/n) ^表示次方计算,就是math.pow
|
|
|
|
|
|
|
|
|
|
# 四、FAQ
|
|
|
|
|
1. 为什么使用布隆过滤器而不是直接使用set?
|
|
|
|
|
因为set中会存储每个元素的内容,而布隆过滤器仅仅存储元素的指纹
|
|
|
|
|
2. 如果redis不支持布隆过滤器怎么办?
|
|
|
|
|
python 版本 pyreBloom;java版本 orestes-bloomfilter或者hutool中提供的bloomfilter
|