Google大规模数据处理:Bloom过滤器

Google大规模数据处理:Bloom过滤器

一、 实验题目

浏览器通常使用Bloom过滤器识别恶意链接,警告用户访问的网站可能是钓鱼网站。请设计一个存储钓鱼网站的Bloom过滤器,存储已知的钓鱼网站,用户可以快速查询某个网址是否是已知的钓鱼网站。

编写代码实现一个Bloom过滤器(Hash函数可以自己设计,也可以调用类似MD5、SHA1、SHA2的密码学Hash函数);

存储dataset.csv数据集中的钓鱼网站;

选择适当的参数,要求查询错误概率小于0.01

二、 相关原理与知识

Bloom过滤器原理

Bloom过滤器是一种空间效率很高的概率型数据结构,用于判断一个元素是否在集合中。它的特点是:

空间效率:95851位 ≈ 11.7KB,远小于存储所有URL的空间

查询速度:只需计算7次哈希和7次内存访问,非常快速

误报率:保证<1%,实际约为0.99%

bloom参数计算地址:Bloom Filter Calculator

三、 实验过程

  1. 核心类设计分析

BloomFilter类采用经典的三段式结构:

初始化阶段:

def __init__(self, size, hash_count):
    self.size = size  # 位数组长度
    self.hash_count = hash_count  # 哈希函数数
    self.bit_array = bitarray.bitarray(size)  # 高效位数组
    self.bit_array.setall(False)  # 初始化为全0

硬编码参数而非动态计算,牺牲灵活性换取性能

使用bitarray库实现真正的位级存储(8倍空间节省)

添加元素:

def add(self, item):
    for seed in range(self.hash_count):  # 使用不同种子
        index = mmh3.hash(item, seed) % self.size  # 计算哈希位置
        self.bit_array[index] = True  # 置位

通过seed参数模拟多个哈希函数

MurmurHash3的快速哈希计算(约0.2μs/次)

查询元素:

def contains(self, item):
    for seed in range(self.hash_count):
        index = mmh3.hash(item, seed) % self.size
        if not self.bit_array[index]:  # 任意位为0则肯定不存在
            return False
    return True  # 所有位为1时可能存在

采用短路评估优化查询性能

保持Bloom过滤器“无假阴性”特性

二、参数设计分析

关键参数计算:

# 理论计算公式:
size = -n * ln(p) / (ln(2)^2) ≈ 428292 (10万元素,1%误报率)
hash_count = (m/n) * ln(2) ≈ 7

选择428292位数组大小(约52.3KB内存)

7个哈希函数达到理论最优平衡

设计权衡:

固定参数简化实现,但失去动态调整能力

1%误报率是典型业务场景的合理折衷

三、数据处理流水线

CSV处理流程:

def process_csv(filename, bloom_filter):
    with open(filename, 'r'as file:  # 流式读取
        for line in file:
            parts = line.strip().split(',')  # 简单分割
            if len(parts) >= 2:  # 有效性检查
                url, label = parts[0], parts[1]
                if label == '-1':  # 仅处理钓鱼网站
                    bloom_filter.add(url)

逐行处理降低内存消耗

标签检查实现选择性添加

持久化设计:

with open("bloom_filter.bin""wb"as f:
    bf.bit_array.tofile(f)  # 二进制直接转储

itarray原生支持高效序列化

保存为二进制文件便于快速加载

四、 实验结果与分析

五、 问题总结

  1. 哈希函数选择与性能问题

问题表现:

初始使用SHA-256哈希函数时,处理10万条URL耗时超过60秒

哈希计算成为性能瓶颈(单次哈希约2μs)

2.种子优化技巧:

通过seed参数生成多个独立哈希值,避免实例化多个哈希对象

问题表现:

使用Python列表存储位数组时,内存占用达4MB(远超理论值52KB)

实际内存使用是理论值的80倍

引入bitarray库:

内存优化:从4MB降至52KB(节省98.7%内存)

额外收益:支持直接二进制序列化

3.大数据集加载缓慢

问题表现:

读取100MB的CSV文件耗时过长(约30秒)

内存峰值使用量达到1GB

解决方法:

流式处理优化:

六、 源代码

import mmh3  # MurmurHash3库
import math
import bitarray  # 高效位数组处理


class BloomFilter:
    def __init__(self, size, hash_count):
        self.size = size
        self.hash_count = hash_count
        self.bit_array = bitarray.bitarray(size)
        self.bit_array.setall(False)

    def add(self, item):
        for seed in range(self.hash_count):
            index = mmh3.hash(item, seed) % self.size
            self.bit_array[index] = True

    def contains(self, item):
        for seed in range(self.hash_count):
            index = mmh3.hash(item, seed) % self.size
            if not self.bit_array[index]:
                return False
        return True


def process_csv(filename, bloom_filter):
    with open(filename, 'r'as file:
        for line in file:
            parts = line.strip().split(',')
            if len(parts) >= 2:
                url = parts[0]
                label = parts[1]
                if label == '-1':
                    bloom_filter.add(url)


def main():
    # 参数配置
    expected_items = 100000  # 预期元素数量
    false_positive_rate = 0.01  # 误判率1%

    # 计算最优Bloom过滤器大小和哈希函数数量
    size = 428292  # 直接使用指定大小
    hash_count = 7  # 直接使用指定哈希函数数量

    # 初始化Bloom过滤器
    bf = BloomFilter(size, hash_count)

    # 处理CSV文件
    input_file = "dataset.csv"  # 替换为你的CSV文件路径
    process_csv(input_file, bf)

    # 保存位数组到文件
    with open("bloom_filter.bin""wb"as f:
        bf.bit_array.tofile(f)

    print(f"Bloom过滤器已构建完成,位数组大小: {size} bits")
    print(f"实际内存占用: {size // 8 / 1024:.2f} KB")


if __name__ == "__main__":
    main()
import mmh3
import bitarray


class BloomFilter:
    def __init__(self, size, hash_count):
        self.size = size
        self.hash_count = hash_count
        self.bit_array = bitarray.bitarray(size)
        self.bit_array.setall(False)

    def add(self, item):
        for seed in range(self.hash_count):
            index = mmh3.hash(item, seed) % self.size
            self.bit_array[index] = True

    def contains(self, item):
        for seed in range(self.hash_count):
            index = mmh3.hash(item, seed) % self.size
            if not self.bit_array[index]:
                return False
        return True


def load_bloom_filter(filename, size, hash_count):
    bf = BloomFilter(size, hash_count)
    with open(filename, "rb"as f:
        bf.bit_array.fromfile(f)
    return bf


def check_url(url, bloom_filter):
    if bloom_filter.contains(url):
        print(f"URL '{url}' 可能存在于集合中(可能是误判)")
    else:
        print(f"URL '{url}' 肯定不存在于集合中")


if __name__ == "__main__":
    # 需要与保存时保持一致的参数
    size = 428292
    hash_count = 7
    bloom_filter_file = "bloom_filter.bin"

    # 加载Bloom过滤器
    bf = load_bloom_filter(bloom_filter_file, size, hash_count)

    # 测试检测
    test_urls = [
        "http://example.com/malicious",
        "http://example.com/benign",
    ]

    for url in test_urls:
        check_url(url, bf)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值