python+redis实现布隆过滤器(含redis5.0版本以上和5.0以下版本的两份代码)

布隆过滤器是一种空间效率极高的概率数据结构,用于测试一个元素是否是集合的成员。如果布隆过滤器返回 False,则元素绝对不在集合中。如果返回 True,则元素可能在集合中,但也可能是一个误报。布隆过滤器利用了多个不同的哈希函数对元素进行哈希,并将结果的位置在一个位数组上设置为 1。

1. redis5.0以上版本的布隆过滤器实现(RedisBloom)

RedisBloom 是 Redis 的一个模块,提供了 Bloom Filter、Cuckoo Filter、Count-Min Sketch 和 Top-K 这些数据结构。这些数据结构特别适用于处理海量数据的场景,因为它们是空间有效和计算高效的。

1.1 安装 RedisBloom:

确保你已经安装了 Redis。然后,你可以从 RedisBloom 的 GitHub 存储库下载并构建它。

bash 复制代码
git clone --recursive https://github.com/RedisBloom/RedisBloom.git
cd RedisBloom
make

这将生成一个名为 redisbloom.so 的共享对象文件。

1.2 运行 Redis 与 RedisBloom 模块:

bash 复制代码
redis-server --loadmodule ./redisbloom.so

1.3 使用 Bloom Filter:

接下来,你可以使用 redis-cli 或任何 Redis 客户端库与 Redis 交互。

例如,使用 redis-cli:

bash 复制代码
redis-cli

添加元素到 Bloom Filter:

bash 复制代码
127.0.0.1:6379> BF.ADD myfilter item1
(integer) 1

检查元素是否存在:

bash 复制代码
127.0.0.1:6379> BF.EXISTS myfilter item1
(integer) 1
127.0.0.1:6379> BF.EXISTS myfilter item2
(integer) 0

1.4 Python 示例:

要在 Python 中使用 RedisBloom,你需要安装 redis-py 和 redisbloom 客户端库。

bash 复制代码
pip install redis redisbloom

然后,你可以这样使用:

python 复制代码
import redis
from redisbloom.client import Client

client = Client(host='localhost', port=6379)
client.bfCreate('myfilter', errorRate=0.01, capacity=10000)
client.bfAdd('myfilter', 'item1')
print(client.bfExists('myfilter', 'item1'))  # True
print(client.bfExists('myfilter', 'item2'))  # False

2. redis5.0以下版本的布隆过滤器实现(手写实现)

2.1 安装必要的库:

bash 复制代码
pip install redis bitarray

2.2 布隆过滤器实现:

python 复制代码
from datetime import datetime
import redis
from hashlib import md5


class SimpleHash(object):
    def __init__(self, cap, seed):
        self.cap = cap
        self.seed = seed

    def hash(self, value):
        ret = 0
        for i in range(len(value)):
            ret += self.seed * ret + ord(value[i])
        return (self.cap - 1) & ret


class BloomFilter(object):
    def __init__(self, host='10.9.50.171', port=6379, db=1, password='asmd888', key='bloomfilter'):
        """
        :param host: the host of Redis
        :param port: the port of Redis
        :param db: witch db in Redis
        :param blockNum: one blockNum for about 90,000,000; if you have more strings for filtering, increase it.
        :param key: the key's name in Redis
        """
        self.server = redis.Redis(host=host, port=port, db=db, password=password, decode_responses=True)
        self.bit_size = 1 << 25  # Redis的String类型最大容量为512M,现使用4M,误报率为(九/一百万)
        self.seeds = [5, 7, 11, 13, 31, 37, 61]
        # self.seeds = [5, 7, 11, 13, 31]
        self.key = key
        self.hashfunc = []
        for seed in self.seeds:
            self.hashfunc.append(SimpleHash(self.bit_size, seed))

    def isContains(self, str_input):
        """
        # 判断是否存在
        :param str_input:
        :return:
        """
        if not str_input:
            return False
        m5 = md5()
        m5.update(str_input.encode())
        str_input = m5.hexdigest()
        ret = True
        for f in self.hashfunc:
            loc = f.hash(str_input)
            bit_name = self.server.getbit(self.key, loc)
            ret = ret & bit_name
        return ret

    def insert(self, str_input):
        """
        添加新的值
        :param str_input:
        :return:
        """
        m5 = md5()
        m5.update(str_input.encode())
        str_input = m5.hexdigest()
        for f in self.hashfunc:
            loc = f.hash(str_input)
            self.server.setbit(self.key, loc, 1)


if __name__ == '__main__':
    """ 第一次运行时会显示 not exists!,之后再运行会显示 exists! """
    bf = BloomFilter()
    old = datetime.now()
    name = 'www.baidusasdfasf.asdd4564asd'
    if bf.isContains(name):  # 判断字符串是否存在
        print('exists!')
    else:
        print('not exists!')
        bf.insert(name)
    new = datetime.now()
    print(new - old)
相关推荐
VidDown3 小时前
24fps 转 25fps 不只是改个数字:帧率转换、PAL/NTSC 与音频补偿
python·网络协议·音视频·视频编解码·视频
骇客野人5 小时前
在麒麟操作系统上 分别安装 jdk1.8, 达梦数据库,redis ,memcache 的操作实施方案和步骤
数据库·redis·memcached
死磕音视频5 小时前
让小模型做选择题:限定候选项并读取 logits 概率的入门实践(附 Python 代码)
开发语言·python·大模型·文本分类·transformers
凤山老林5 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
pride.li7 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
databook7 小时前
用 Pydantic AI 从零搭建一个能干活的 AI Agent
人工智能·python
顽疲7 小时前
Java vue 养老系统源码详解:月账单 care_month_bill 与 Quartz 扣费 Job 实践
java·开发语言·vue.js·vue养老·springboot养老·java养老
康小旺7 小时前
把 markitdown 做成 Windows 桌面版:拖进文档就出 Markdown,附 233MB→64MB 打包裁剪全过程
python
Wang's Blog8 小时前
Java 项目实战: 交友项目 - 安装开发工具与环境准备
java·开发语言·交友
.Bryce.8 小时前
在智能体中使用A2A工具:让大模型自己决定“该找谁帮忙“
android·java·服务器·redis·后端·agent·a2a