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

yizhihongxing

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日

相关文章

  • pywinauto自动化测试使用经验

    Pywinauto自动化测试使用经验攻略 Pywinauto是一个用于Windows GUI自动化测试的Python库,可以模拟用户操作,自动化测试GUI应用程序。本篇攻略将为您介绍如何使用Pywinauto进行自动化测试,包括安装、环境配置、基础API使用和实际示例。 安装与配置 安装Pywinauto需要先安装Python,推荐使用Python3.x版本…

    python 2023年5月19日
    00
  • Python csv文件的读写操作实例详解

    下面我将为你讲解如何进行Python csv文件的读写操作。 1. 什么是csv文件 csv全称Comma-Separated Values,即逗号分隔值文件,是一种常见的电子表格或数据库存储格式,用逗号来分割一行中各个字段的数据。 2. 如何读取csv文件 使用Python内置的csv模块可以很方便地对csv文件进行读取。下面是一个读取csv文件的示例: …

    python 2023年6月3日
    00
  • python实现进程间通信简单实例

    如果我们在Python中使用多进程,那么进程之间的通信必须使用IPC(Inter-Process Communication)机制。本文将以两个例子为例,介绍一些Python中的进程间通信方法。 1. 使用共享内存进行IPC 共享内存是两个进程之间通信的一种常见方式。通过指定共享内存的地址,进程可以读取和写入此内存区域并进行通信。下面是一个Using Pyt…

    python 2023年6月2日
    00
  • Python基于百度AI实现OCR文字识别

    Python基于百度AI实现OCR文字识别攻略 一、前置条件 注册百度AI,获取API Key和Secret Key 安装 Python3,并安装所需第三方库 requests bash pip install requests 二、百度AI接口调用 导入requests库 python import requests 设置请求url和headers信息 p…

    python 2023年5月18日
    00
  • python3 requests中文乱码之压缩格式问题解析

    让我给您介绍一下 Python3 requests 中文乱码之压缩格式问题解析的完整攻略。 问题解析 在使用 Python 中的 requests 发送请求时,如果返回的数据中包含中文字符,有时候会出现乱码问题。这可能是由于原始文本使用了压缩格式,而 requests 默认不会进行解压缩,导致出现乱码问题。 解决方法 要解决这个问题,我们需要在 reques…

    python 2023年5月20日
    00
  • Python的数据结构与算法的队列详解(3)

    Python的数据结构与算法的队列详解(3) 在本文中,我们将继续讲解Python的数据结构与算法的队列,包括队列的实现方式、队列的应用场景及队列的注意项。同时,我们还将提供两个示例说明,以帮助读者更好地理解队列的使用方法。 队列的实现 队列是一种先进先出(FIFO)的数据结构,它可以用于存储一组元素,支持在队列的末尾添加元素,在队列的开头删除元素。在Pyt…

    python 2023年5月13日
    00
  • python实现Excel多行多列的转换的示例

    下面我将介绍如何用 Python 实现 Excel 多行多列的转换示例,包括以下内容: 安装必要的库 读取Excel文件数据 转换Excel文件数据 写入转换后数据到新的Excel文件中 以下是完整实例教程: 1. 安装必要的库 这个程序需要用到 pandas 和 openpyxl 库,所以需要先安装: pip install pandas openpyxl…

    python 2023年5月13日
    00
  • Python 基础之字符串string详解及实例

    Python 基础之字符串string详解及实例 什么是字符串? 在 Python 中,字符串是用引号括起来的一串字符,可以使用单引号或双引号表示,例如: string1 = ‘This is a string’ string2 = "This is also a string" 其中,string1 和 string2 都是字符串对象。…

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