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)
相关推荐
软件黑马王子4 分钟前
C#初级教程(4)——流程控制:从基础到实践
开发语言·c#
莫忘初心丶4 分钟前
在 Ubuntu 22 上使用 Gunicorn 启动 Flask 应用程序
python·ubuntu·flask·gunicorn
闲猫7 分钟前
go orm GORM
开发语言·后端·golang
李白同学2 小时前
【C语言】结构体内存对齐问题
c语言·开发语言
希忘auto2 小时前
详解Redis在Centos上的安装
redis·centos
黑子哥呢?3 小时前
安装Bash completion解决tab不能补全问题
开发语言·bash
失败尽常态5233 小时前
用Python实现Excel数据同步到飞书文档
python·excel·飞书
2501_904447743 小时前
OPPO发布新型折叠屏手机 起售价8999
python·智能手机·django·virtualenv·pygame
青龙小码农3 小时前
yum报错:bash: /usr/bin/yum: /usr/bin/python: 坏的解释器:没有那个文件或目录
开发语言·python·bash·liunx
大数据追光猿3 小时前
Python应用算法之贪心算法理解和实践
大数据·开发语言·人工智能·python·深度学习·算法·贪心算法