python 布隆过滤器
import mmh3 import redis import math class PyBloomFilter: # 内置100个随机种子 SEEDS = [ 543, 460, 171, 876, 796, 607, 650, 81, 837, 545, 591, 946, 846, 521, 913, 636, 878, 735, 414, 372, 344, 324, 223, 180, 327, 891, 798, 933, 493, 293, 836, 10, 6, 544, 924, 849, 438, 41, 862, 648, 338, 465, 562, 693, 979, 52, 763, 103, 387, 374, 349, 94, 384, 680, 574, 480, 307, 580, 71, 535, 300, 53, 481, 519, 644, 219, 686, 236, 424, 326, 244, 212, 909, 202, 951, 56, 812, 901, 926, 250, 507, 739, 371, 63, 584, 154, 7, 284, 617, 332, 472, 140, 605, 262, 355, 526, 647, 923, 199, 518 ] def __init__(self, capacity=2000000000, error_rate=0.00000001, conn=None, key='BloomFilter'): """ 初始化布隆过滤器。 :param capacity: 预先估计要去重的数量。 :param error_rate: 错误率。 :param conn: Redis 的连接客户端。 :param key: 在 Redis 中键的名字前缀。 """ self.m = math.ceil(capacity * math.log2(math.e) * math.log2(1 / error_rate)) # 需要的总 bit 数 self.k = 1 # 需要最少的 hash 次数 self.mem = math.ceil(self.m / 8 / 1024 / 1024) # 需要的多少 M 内存 self.block_size_gb = 10 # 每个内存块的大小(GB) self.block_size_bits = self.block_size_gb * 1024 * 1024 * 8 # 每个内存块的大小(bits) self.blocknum = min(math.ceil(self.mem / self.block_size_gb), 256) # 需要多少个 10GB 的内存块 self.seeds = self.SEEDS[:self.k] # 只需要一个种子用于单哈希 self.key = key self.N = 2 ** 31 - 1 self.redis = conn print("self.m", self.m) print("self.k", self.k) print("self.mem", self.mem) print("self.block_size_bits", self.block_size_bits) print("self.blocknum", self.blocknum) print("self.seeds", self.seeds) def add(self, value): """ 将元素添加到布隆过滤器中。 :param value: 要添加的元素。 """ # 计算 Redis 键名 name = f"{self.key}_{ord(value[0]) % self.blocknum}" # 获取哈希值列表 hashs = self.get_hashes(value) # 设置每个哈希位置的位为 1 for hash in hashs: block_index = hash // self.block_size_bits bit_offset = hash % self.block_size_bits block_name = f"{name}_{block_index}" self.redis.setbit(block_name, bit_offset, 1) def is_exist(self, value): """ 检查元素是否存在于布隆过滤器中。 :param value: 要检查的元素。 :return: 如果存在返回 True,否则返回 False。 """ # 计算 Redis 键名 name = f"{self.key}_{ord(value[0]) % self.blocknum}" # 获取哈希值列表 hashs = self.get_hashes(value) exist = True # 检查每个哈希位置的位是否为 1 for hash in hashs: block_index = hash // self.block_size_bits bit_offset = hash % self.block_size_bits block_name = f"{name}_{block_index}" exist = exist and bool(self.redis.getbit(block_name, bit_offset)) return exist def get_hashes(self, value): """ 获取元素的哈希值列表。 :param value: 要哈希的元素。 :return: 哈希值列表。 """ hashs = list() for seed in self.seeds: hash_value = mmh3.hash(value, seed) if hash_value >= 0: hashs.append(hash_value) else: hashs.append(self.N - hash_value) return hashs # 创建 Redis 连接池 pool = redis.ConnectionPool(host='127.0.0.1', port=6379, db=8) # 创建 Redis 客户端 conn = redis.Redis(connection_pool=pool) # 创建布隆过滤器实例 bf = PyBloomFilter(conn=conn) # 测试添加元素和检查元素是否存在 bf.add("example") print(bf.is_exist("example")) # 存在 输出应为 True print(bf.is_exist("test")) # 不存在 输出应为 False
去重方式有那些
1. 数据库 唯一索引
比如MySQL,es等
2. redis set
3. 布隆过滤器
4. 时间 + redis set
5.
如果觉得对您有帮助,麻烦您点一下推荐,谢谢!
好记忆不如烂笔头
好记忆不如烂笔头
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步