Python Counting Bloom Filter原理与实现详细介绍

Python Counting Bloom Filter 原理与实现详细介绍

概述

Counting Bloom Filter 是 Bloom Filter 的升级版,除了具有 Bloom Filter 的高效性和空间节省性之外,还可以处理删除元素的问题。

这篇文章将详细介绍 Counting Bloom Filter 的原理、实现细节以及应用场景。

原理

Bloom Filter 简介

Bloom Filter 是一种空间效率非常高的随机数据结构,用于判断一个元素是否属于某个集合。它的核心思想是使用 k 个不同的哈希函数,将输入元素分别哈希成 m 位的二进制向量,并将向量中的每一位设置为 1。当需要查询某个元素是否在集合中时,将该元素经过哈希函数,检查它所对应的 m 位是否全部为 1。如果全部为 1,则认为该元素在集合中;如果存在任一位不为 1,则认为该元素不在集合中。

但是 Bloom Filter 也存在一定的缺点,由于所有的元素都被哈希到一张很小的表中,一旦 Bloom Filter 填满,就无法再添加新元素。而且 Bloom Filter 无法支持元素删除操作。

Counting Bloom Filter 原理

Counting Bloom Filter 稍作修改,它们并不使用简单的向量的位。相反,对于每个插入的元素,它们使用一个计数器。一旦所有元素都插入,则可以跟踪每个元素在数组中的出现次数。

当我们想要查询某个元素是否在 Counting Bloom Filter 中时,对应的哈希值被发送到元素的位置,此时计数器的值表示它已经被添加到 Counting Bloom Filter 中的次数。由于元素可能被计数器递减几次,所以 Counting Bloom Filter 不能被视为检测元素的绝对存在。

Counting Bloom Filter 对于查询某个元素是否存在的问题,可以保证不会产生误判,但会产生误报。

Counting Bloom Filter 实现

  1. 初始化

Counting Bloom Filter 的第一步是创建一个大小为 m 的计数器数组,其中每个计数器都是一个整数,并且值为 0。除此之外,还需要确定 k 个哈希函数。这提供了两个因素 - 首先,每个元素将被哈希至少一次;其次,尽管 Bloom Filter 是基于随机方法的,但是这些哈希函数仍然必须满足不同的互补性质。

  1. 添加元素

为了在 Counting Bloom Filter 中添加元素,每个元素的 k 个哈希值最好被插入到数组中,每个哈希对应的计数器都应该加 1。如果 Counting Bloom Filter 已经使用了所有元素,那么未出现的元素将是一个新的找到的位置。

  1. 删除元素

使用 Counting Bloom Filter 删除元素比插入更加复杂。如果从添加元素的数组中删除元素,那么如果有另一个元素而且它用相同的哈希值覆盖那么它会一起删除。意思是 Counting Bloom Filter 不能将计数器减少到负数。

为了解决这个问题,可以将 Counting Bloom Filter 的计数器替换为倍精度整数,这样它们可以支持减法。在删除指定元素时,将对应的 k 个哈希值的计数器相应地降低 1。

  1. 查询元素

查询元素时,只需将元素的哈希值发送到数组中。如果对应的 k 个计数器的值均大于 0,则表明该元素在 Counting Bloom Filter 内。

实例说明

示例 1: 去重

下面是一个使用 Counting Bloom Filter 去重的示例:

class CountingBloomFilter:
    def __init__(self, m, k):
        self.m = m
        self.k = k
        self.counters = [0] * m
        self.hash_funcs = [hashlib.sha256(str(i).encode()).hexdigest() for i in range(k)]

    def add(self, element):
        for i in range(self.k):
            index = int(hashlib.sha256(str(element + self.hash_funcs[i]).encode()).hexdigest(), 16) % self.m
            self.counters[index] += 1

    def remove(self, element):
        for i in range(self.k):
            index = int(hashlib.sha256(str(element + self.hash_funcs[i]).encode()).hexdigest(), 16) % self.m
            if self.counters[index] > 0:
                self.counters[index] -= 1

    def __contains__(self, element):
        for i in range(self.k):
            index = int(hashlib.sha256(str(element + self.hash_funcs[i]).encode()).hexdigest(), 16) % self.m
            if self.counters[index] == 0:
                return False
        return True

if __name__ == "__main__":
    cbf = CountingBloomFilter(100, 5)
    urls = ["www.google.com", "www.baidu.com", "www.github.com", "www.google.com"]
    for url in urls:
        cbf.add(url)
    print("www.google.com" in cbf) # True
    print("www.tencent.com" in cbf) # False

在这个例子中,使用了 5 个哈希函数,数组大小为 100。添加了 4 个 url,但有一个 url 重复了。因为 Counting Bloom Filter 使用了计数器,因此不会将重复元素添加进去。在最后,容易发现 www.google.com 是在布隆过滤器中的。

示例 2: 防止重放攻击

下面是一个使用 Counting Bloom Filter 防止重放攻击的示例:

class CountingBloomFilter:
    def __init__(self, m, k):
        self.m = m
        self.k = k
        self.counters = [0] * m
        self.hash_funcs = [hashlib.sha256(str(i).encode()).hexdigest() for i in range(k)]

    def add(self, element):
        for i in range(self.k):
            index = int(hashlib.sha256(str(element + self.hash_funcs[i]).encode()).hexdigest(), 16) % self.m
            self.counters[index] += 1

    def remove(self, element):
        for i in range(self.k):
            index = int(hashlib.sha256(str(element + self.hash_funcs[i]).encode()).hexdigest(), 16) % self.m
            if self.counters[index] > 0:
                self.counters[index] -= 1

    def __contains__(self, element):
        for i in range(self.k):
            index = int(hashlib.sha256(str(element + self.hash_funcs[i]).encode()).hexdigest(), 16) % self.m
            if self.counters[index] == 0:
                return False
        return True

if __name__ == "__main__":
    cbf = CountingBloomFilter(100, 5)

    nonce = "123456"
    message = "something"

    # 先将 nonce 放入 Counting Bloom Filter 中
    cbf.add(nonce)

    # 第一次签名时,检查 nonce 是否存在
    if nonce in cbf:
        signature = sign(message)

    # 第二次签名时检查 nonce 是否存在
    if nonce in cbf:
        signature = sign(message)
    else:
        raise Exception("Nonce has been used!")

在这个例子中,一个随机数被用作 nonce,它被放到 Counting Bloom Filter 中来防止重复签名。在第一次签名时,nonce 被检查是否存在,如果存在则签名成功。第二次签名时,再次检查 Counting Bloom Filter 中是否存在 nonce。如果存在就是重放攻击,签名将失败,并将引发异常。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python Counting Bloom Filter原理与实现详细介绍 - Python技术站

(0)
上一篇 2023年5月14日
下一篇 2023年5月14日

相关文章

  • 使用Python爬虫库requests发送请求、传递URL参数、定制headers

    以下是关于使用Python爬虫库requests发送请求、传递URL参数、定制headers的攻略: 使用Python爬虫库requests发送请求、传递URL参数、定制headers requests是Python中一个流行的HTTP库,可以用于向Web服务器发送HTTP请求和接收响应。以下是使用Python爬虫库requests发送请求、传递URL参数、…

    python 2023年5月14日
    00
  • python自动化办公操作PPT的实现

    下面我会详细讲解“Python自动化办公操作PPT的实现”的完整攻略。 1. 准备工作 在开始Python自动化办公操作PPT之前,我们需要安装相关依赖库。首先确保已经安装Python,然后使用pip或conda安装以下几个库: python-pptx:用于操作PPT文件 pandas:用于处理Excel表格数据(可选) 安装完成后,可以使用以下代码检测库是…

    python 2023年5月18日
    00
  • 在Mac OS系统上安装Python的Pillow库的教程

    下面是在Mac OS系统上安装Python的Pillow库的完整攻略: 步骤一:安装pip Pillow库依赖于pip包管理系统,因此首先需要在Mac OS系统上安装pip。在终端中输入以下命令: sudo easy_install pip 输入您的管理员密码(在系统提示之后),然后等待安装完成。 步骤二:安装Pillow 在终端中输入以下命令: pip i…

    python 2023年6月2日
    00
  • python超详细实现字体反爬流程

    首先我们需要了解字体反爬的原理:通过在页面中加载自定义字体文件,然后在CSS样式中通过Unicode数值来替换文本内容,从而混淆文本信息,防止爬虫直接获取页面信息。因此,我们需要解决的是如何准确地将Unicode数值转换成正确的文本信息。 下面是python超详细实现字体反爬流程的攻略: 1. 获取页面字体文件 在爬取页面之前,我们需要先获取页面字体文件,通…

    python 2023年5月20日
    00
  • Python 运行一个它不应该运行的 if-case!

    【问题标题】:Python runs a if-case that it should not!Python 运行一个它不应该运行的 if-case! 【发布时间】:2023-04-03 19:06:01 【问题描述】: 我有这个代码: def random_answerlist(self): self.li = [] self.winning_button…

    Python开发 2023年4月8日
    00
  • Python的缺点和劣势分析

    Python的缺点和劣势分析 Python是一种非常流行且使用广泛的编程语言,但在其方便和易用性之外,也有一些缺点和劣势。在本文中,我们将探究Python的缺点和劣势分析。 1. 较慢的执行速度 Python是一种解释型语言,因此其执行速度通常较慢。与其他编译型语言(如C++或Java)相比,Python通常需要更多的运行时间来执行相同的操作。这主要是由于P…

    python 2023年5月30日
    00
  • Python机器学习库scikit-learn使用详解

    Python机器学习库scikit-learn使用详解 什么是scikit-learn scikit-learn是一个用于机器学习的Python库。它建立在NumPy、SciPy和matplotlib之上,是机器学习、数据挖掘和数据分析的重要工具之一。scikit-learn提供了许多经典的机器学习算法,如分类、回归、聚类和降维等。同时,它还提供了数据预处理…

    python 2023年5月23日
    00
  • python 实现图片上传接口开发 并生成可以访问的图片url

    下面是关于「Python 实现图片上传接口开发并生成可以访问的图片URL」的完整攻略。 1. 需要的工具和库 在实现图片上传接口和生成可以访问的图片URL的过程中,我们需要的工具和库如下: Python(3.x 以上版本) Flask(Python 的 Web 框架) Werkzeug(Flask 内置使用的 WSGI 工具,也用于 Flask 上传文件) …

    python 2023年5月18日
    00
合作推广
合作推广
分享本页
返回顶部