布隆过滤器原理

布隆过滤器原理

什么是布隆过滤器

布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否”可能”存在于一个集合中。它的核心特点是:

  • 如果判定不存在 → 一定不存在(零假阴性)
  • 如果判定存在 → 可能存在(可能有假阳性,但概率可控)

工作原理

布隆过滤器的本质是一个很长的二进制位数组 + 一组哈希函数

初始化

  1. 创建一个长度为 m 的位数组,所有位初始化为 0
  2. 准备 k 个相互独立的哈希函数
位数组:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]  (m=18)
哈希函数:h1(), h2(), h3()                       (k=3)

添加元素

将一个元素加入布隆过滤器时:

def add(element):
    for i in range(k):  # k=3 个哈希函数
        position = hash_i(element) % m
        bits[position] = 1

以元素 “user:1001” 为例:

h1("user:1001") % 18 = 3  →  bits[3] = 1
h2("user:1001") % 18 = 7  →  bits[7] = 1
h3("user:1001") % 18 = 12 →  bits[12] = 1

添加后位数组状态:

[0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0]
        ↑           ↑           ↑

查询元素

判断一个元素是否在集合中:

def contains(element):
    for i in range(k):
        position = hash_i(element) % m
        if bits[position] == 0:
            return False  # 一定不存在
    return True  # 可能存在

如果检测 “user:1002″:

h1("user:1002") % 18 = 5  → bits[5] == 1? → 是
h2("user:1002") % 18 = 9  → bits[9] == 1? → 是
h3("user:1002") % 18 = 14 → bits[14] == 1? → 是
→ 返回 True("可能存在",实际可能不存在——假阳性)

如果检测 “user:9999″:

h1("user:9999") % 18 = 1  → bits[1] == 1? → 否
→ 立即返回 False(一定不存在)

假阳性率

布隆过滤器的核心参数决定了它的性能:

参数 含义 对假阳性率的影响
m(位数组长度) 越大空间越多,假阳性率越低 反比
n(元素个数) 已添加元素越多,假阳性率越高 正比
k(哈希函数数) 越多随机性越好,但过多会填满位数组 有最优值

最优哈希函数数量

k = (m / n) × ln(2)

假阳性率公式

P = (1 - e^(-kn/m))^k

常见配置参考

期望元素数 n 假阳性率 P 位数组大小 m 哈希函数数 k
100 万 1% 约 12 MB 7
100 万 0.1% 约 18 MB 10
1000 万 1% 约 120 MB 7

布隆过滤器的局限性

不支持删除

布隆过滤器的位可能被多个元素共享,直接清零会误删其他元素。如果需要支持删除,可以使用 Counting Bloom Filter(用计数器代替位)。

无法遍历

布隆过滤器只能回答”是否存在”,不能遍历或返回存储的元素。

全量数据重建

如果初始数据没有预加载,需要遍历所有合法 Key 来初始化布隆过滤器。

在 Redis 中的实现

方案一:自建(使用位图)

SETBIT bloom:users 0 1
SETBIT bloom:users 1 0
...

但自己实现哈希函数和位操作比较麻烦。

方案二:RedisBloom 模块(推荐)

Redis 官方提供了 RedisBloom 模块:

BF.ADD bloom:users user:1001
BF.EXISTS bloom:users user:1001  → (integer) 1
BF.EXISTS bloom:users user:9999  → (integer) 0
BF.MADD bloom:users user:1001 user:1002
BF.MEXISTS bloom:users user:1001 user:1003

# 自定义参数
BF.RESERVE bloom:users 0.01 1000000  # 假阳性率 1%,容量 100 万

与缓存穿透的结合

顺序:
1. 请求某个 Key
2. 先在布隆过滤器中判断
   └── 不存在 → 直接返回 null(拦截在缓存层之前)
   └── 可能存在 → 继续查缓存 → 查数据库

布隆过滤器在缓存穿透场景中的核心价值:用极小的内存开销,确定性地排除掉不存在的数据请求

总结

布隆过滤器的本质是”用少量假阳性换取空间极致压缩”。在缓存穿透防护中,它的价值不是”完全精确”,而是”可以确定地说不”。对于存在 99% 无效请求的攻击场景,布隆过滤器可以用几 MB 内存,将 99% 的无效请求挡在缓存和数据库之外。理解和合理配置其参数(m、n、k),是在面试中展示技术深度的关键。

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容