如何在Python中使用Redis布隆过滤器防止缓存穿透

夏强姑娘_8610

夏强姑娘_8610

2026-10-12

578人浏览

原创

redis原生不支持bloomfilter命令,需通过redis stack加载redisbloom模块(支持bf.add/bf.exists)或用python在客户端手动实现:基于mmh3哈希+redis.setbit维护位图,bit_size与hash_count需按容量和误判率合理配置,且add操作须与数据库写入强一致。

如何在python中使用redis布隆过滤器防止缓存穿透

布隆过滤器不是Redis原生命令,得自己搭或选封装库

Redis 本身不提供 BloomFilter 命令(6.2+ 虽有 RedisBloom 模块,但需额外部署 Redis Stack 或加载模块),所以 Python 里直接用 redis-py 是调不出 BF.ADD 这类指令的。常见错误是查到“Redis 支持布隆过滤器”就直接连上去调用,结果报 ResponseError: unknown command `BF.ADD`。

实际落地只有两条路:

  • 走 Redis 官方扩展:装 Redis Stack(含 RedisBloom 模块),然后用 redis-py 调 BF.ADD/BF.EXISTS
  • 纯客户端实现:用 pybloom-live 或 mmh3 + redis.setbit 自己维护一个位图(BitArray)存在 Redis 里

多数中小团队选第二条——不改基础设施、部署零成本、逻辑可控。但要注意:pybloom-live 的 BloomFilter 对象是内存态的,不能直接存 Redis;必须用它算哈希,再把位图写进 Redis 的 String 类型里。

用 mmh3 + setbit 手动实现最稳

这是生产环境最常被验证的方式,不依赖外部模块(除了 mmh3),兼容所有 Redis 版本,且能精确控制每个 bit 位置。核心就是:把 key 映射成多个 hash 值,对每个值取模后执行 redis.setbit(key, offset, 1)。

关键点:

  • bit_size 要足够大:比如预估最多存 100 万个有效 ID,误判率压到 0.1%,按公式算出来至少要 140 万 bit(约 175KB),别拍脑袋设 10 万
  • 哈希函数数量建议固定为 5~7 个,太少误判高,太多写压力大,mmh3.hash(item, i) 的 i 就是用来生成不同种子的
  • 所有写操作(新增 ID)必须和数据库写入强一致:比如插入商品成功后,立刻 bloom_filter.add(product_id),否则漏写就会导致“真实存在却被拦截”

示例片段:

python 查询技能
python 查询技能

查询客流数据,输出JSON格式,可直接导入Bitable等可视化工具

下载
import redis
import mmh3

class RedisBloom:
    def __init__(self, client, key, bit_size=1400000, hash_count=5):
        self.redis = client
        self.key = key
        self.bit_size = bit_size
        self.hash_count = hash_count

    def add(self, item):
        for i in range(self.hash_count):
            digest = mmh3.hash(str(item), i) % self.bit_size
            self.redis.setbit(self.key, digest, 1)

    def exists(self, item):
        for i in range(self.hash_count):
            digest = mmh3.hash(str(item), i) % self.bit_size
            if self.redis.getbit(self.key, digest) == 0:
                return False
        return True

业务层怎么嵌入?别在每次请求里初始化布隆过滤器

高频接口如果每次请求都 new 一个 RedisBloom 实例,会重复解析参数、重建对象,浪费 CPU。更糟的是,如果用的是 pybloom-live 的内存版 BloomFilter,还可能因多线程共享导致状态错乱。

正确做法:

  • 把 RedisBloom 实例作为单例或 Flask/Gunicorn worker 级别全局变量初始化(注意:不是 per-request)
  • 确保 key 命名带业务前缀,比如 bloom:product:id,避免不同服务共用一个位图导致误判交叉
  • 拦截逻辑放在缓存查询之前,顺序必须是:bloom.exists(id) → False 就直接返回;True 再查 redis.get(id) → miss 才查 DB

典型错误:把 exists() 放在查完 Redis 之后,那就完全失去“前置拦截”意义了——无效请求已经穿透到缓存层。

删数据时布隆过滤器怎么办?它不支持删除

这是最容易被忽略的坑。BloomFilter 天然不支持 delete,因为某一位可能是多个 key 共享的。一旦商品下架、用户注销,对应 ID 从 DB 删除了,但布隆过滤器里那个 bit 还是 1,后续请求仍会被判定为“可能存在”,继续打到 DB 查一遍空,等于防御失效。

可行解法只有两个:

  • 定期全量重建:比如每天凌晨用当前 DB 全量有效 ID 重建一次布隆过滤器(用新 key 写入,旧 key DEL),适合 ID 变更不频繁的场景
  • 双过滤器滚动切换:运行中始终维护两个 key(bloom:product:id:v1 和 v2),写时同时更新两个;切换时原子 rename,旧 key 等 TTL 自动过期。复杂但实时性强

别信“用计数布隆过滤器(Counting Bloom Filter)”的方案——Redis 里没现成实现,自己用 Hash 存计数反而放大内存和延迟,得不偿失。

Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

python redis

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1711

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

4324

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1689

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

25157

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3067

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3087

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1163

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2403

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程