【算法】布隆过滤器

一、引言

        在现实世界的计算机科学问题中,我们经常需要判断一个元素是否属于一个集合。传统的做法是使用哈希表或者直接遍历集合,但这些方法在数据量较大时效率低下。布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于测试一个元素是否属于集合。本文将详细介绍布隆过滤器的原理、数据结构、使用场景、算法实现,并与其他算法进行对比,最后给出多语言实现及一个实际的服务应用场景代码框架。

二、算法原理

        布隆过滤器由一个很长的二进制向量和一系列随机映射函数组成。当我们要添加一个元素时,该元素会被多个哈希函数映射到二进制向量的不同位置,并将这些位置设为1。查询时,通过同样的哈希函数计算位置,如果所有对应的位置都是1,则该元素可能存在于集合中;如果有任何一个位置是0,则该元素一定不存在于集合中。

        布隆过滤器由一个比特数组(Bit Array)和多个哈希函数组成。

        初始时,所有的比特位都被置为 0。

        当元素被加入时,通过多个哈希函数计算出多个哈希值,然后将对应的比特位设置为 1。

        当查询一个元素是否存在时,同样通过多个哈希函数计算出哈希值,检查对应的比特位,如果所有对应的比特位都为 1,则该元素可能存在;如果有任何一个比特位为 0,则该元素一定不存在。

三、数据结构

布隆过滤器主要包含以下部分:

        一个大的位数组(bit array)。

        一组哈希函数。

四、使用场景

布隆过滤器适用于以下场景:

        网络爬虫过滤已抓取的URL。

        防止缓存穿透,如数据库查询缓存。

        查询重复元素,如邮件系统过滤重复邮件。

        空间敏感:当元素集合非常大,但只关心是否存在时。

        允许误报:当系统可以容忍少量错误判断时。

        快速查找:需要快速判断元素是否在集合中时。

五、算法实现

以下是布隆过滤器的简单实现步骤:

        初始化一个长度为m的位数组,并设置所有位为0。

        选择k个不同的哈希函数,它们将元素映射到位数组的位置。

        添加元素:对元素进行k次哈希,将得到的k个位置设为1。

        查询元素:对元素进行k次哈希,检查所有对应位置是否为1。

六、其他同类算法对比

        哈希表:精确匹配,空间占用大。

        位图(Bitmap):只能处理整数集合,不支持哈希函数。

        Cuckoo Filter:支持删除操作,空间利用率更高。

        后缀数组:适用于字符串搜索,空间和时间效率较高,但实现复杂。

        Trie树:适用于字符串集合,空间效率较高,但存在空间浪费。

七、多语言实现

布隆过滤器的伪代码实现:

java

// Java
public class BloomFilter {private BitSet bitSet;private int bitSetSize;private int addedElements;private static final int[] SEEDS = new int[]{5, 7, 11, 13, 31};public BloomFilter(int bitSetSize) {this.bitSetSize = bitSetSize;this.bitSet = new BitSet(bitSetSize);this.addedElements = 0;}public void add(String element) {for (int seed : SEEDS) {int hash = hash(element, seed);bitSet.set(hash);}addedElements++;}public boolean contains(String element) {for (int seed : SEEDS) {int hash = hash(element, seed);if (!bitSet.get(hash)) {return false;}}return true;}private int hash(String element, int seed) {// Implement a simple hash function}
}

python

# Python
class BloomFilter:def __init__(self, bit_array_size, hash_functions):self.bit_array = [0] * bit_array_sizeself.hash_functions = hash_functionsdef add(self, element):for hash_function in self.hash_functions:index = hash_function(element)self.bit_array[index] = 1def contains(self, element):return all(self.bit_array[hash_function(element)] for hash_function in self.hash_functions)# Example hash functions
def hash_function_1(element):# Implement a simple hash functiondef hash_function_2(element):# Implement another simple hash function

c++

// C++
#include <vector>
#include <functional>class BloomFilter {
private:std::vector<bool> bit_array;std::vector<std::function<size_t(const std::string&)>> hash_functions;public:BloomFilter(size_t size, const std::vector<std::function<size_t(const std::string&)>>& funcs): bit_array(size, false), hash_functions(funcs) {}void add(const std::string& element) {for (const auto& func : hash_functions) {size_t index = func(element) % bit_array.size();bit_array[index] = true;}}bool contains(const std::string& element) const {for (const auto& func : hash_functions) {size_t index = func(element) % bit_array.size();if (!bit_array[index]) {return false;}}return true;}
};

Go

package mainimport ("fmt""github.com/willf/bloom"
)func main() {filter := bloom.New(1000, 5) // 1000 items, 5 hash functions// Add items to the filterfilter.Add([]byte("hello"))filter.Add([]byte("world"))// Test if items are in the filterif filter.Test([]byte("hello")) {fmt.Println("hello is in the filter")}if !filter.Test([]byte("missing")) {fmt.Println("missing is not in the filter")}
}

八、实际服务应用场景代码框架

使用布隆过滤器来防止缓存穿透的简单服务应用场景代码框架:

java

// Java - Cache Service with Bloom Filter
public class CacheService {private final BloomFilter<String> bloomFilter;private final Map<String, String> cache;public CacheService(int cacheSize, int bloomFilterSize) {this.cache = new HashMap<>(cacheSize);this.bloomFilter = new BloomFilter<>(bloomFilterSize);}public String get(String key) {if (!bloomFilter.contains(key)) {// The key is definitely not in the cachereturn null;}// The key might be in the cache, check the actual cachereturn cache.get(key);}public void put(String key, String value) {bloomFilter.add(key);cache.put(key, value);}
}

python

# Python - Cache Service with Bloom Filter
class CacheService:def __init__(self, cache_size, bloom_filter_size):self.cache = {}self.bloom_filter = BloomFilter(bloom_filter_size, [hash_function_1, hash_function_2])def get(self, key):if not self.bloom_filter.contains(key):# The key is definitely not in the cachereturn None# The key might be in the cache, check the actual cachereturn self.cache.get(key)def put(self, key, value):self.bloom_filter.add(key)self.cache[key] = value# Define hash functions
def hash_function_1(element):# Implement a simple hash functiondef hash_function_2(element):# Implement another simple hash function

c++

// C++ - Cache Service with Bloom Filter
#include <unordered_map>
#include <string>class CacheService {
private:BloomFilter bloomFilter;std::unordered_map<std::string, std::string> cache;public:CacheService(size_t bloomFilterSize, const std::vector<std::function<size_t(const std::string&)>>& hashFuncs): bloomFilter(bloomFilterSize, hashFuncs) {}std::string get(const std::string& key) {if (!bloomFilter.contains(key)) {// The key is definitely not in the cachereturn "";}// The key might be in the cache, check the actual cachereturn cache[key];}void put(const std::string& key, const std::string& value) {bloomFilter.add(key);cache[key] = value;}
};

go

// Go - Cache Service with Bloom Filter
package mainimport ("fmt""github.com/willf/bloom"
)type CacheService struct {bloomFilter *bloom.BloomFiltercache       map[string]string
}func NewCacheService(bloomFilterSize int, cacheSize int) *CacheService {return &CacheService{bloomFilter: bloom.New(bloomFilterSize, 5),cache:       make(map[string]string, cacheSize),}
}func (s *CacheService) Get(key string) (string, bool) {if !s.bloomFilter.Test([]byte(key)) {// The key is definitely not in the cachereturn "", false}// The key might be in the cache, check the actual cachevalue, exists := s.cache[key]return value, exists
}func (s *CacheService) Put(key, value string) {s.bloomFilter.Add([]byte(key))s.cache[key] = value
}func main() {service := NewCacheService(1000, 100)service.Put("hello", "world")if value, exists := service.Get("hello"); exists {fmt.Println("Found in cache:", value)}
}

布隆过滤器在 HBase 中的使用:

在 HBase 中,布隆过滤器主要用于以下两个场景:

行键查找(Get 操作):当客户端发起一个 Get 操作来查询特定的行键时,布隆过滤器可以快速判断该行键是否存在于某个 HFile 中,从而避免不必要的磁盘 I/O。

范围扫描(Scan 操作):当客户端执行一个 Scan 操作来检索一定范围内的行键时,布隆过滤器可以帮助跳过那些肯定不包含目标行键的 HFile,减少扫描的数据量。

HBase 支持以下几种布隆过滤器:

  • NONE:不使用布隆过滤器。
  • ROW:对行键使用布隆过滤器。
  • ROWCOL:对行键加列族:列限定符的组合使用布隆过滤器。
  • PREFIX:对行键的前缀使用布隆过滤器。

在 HBase 中配置布隆过滤器、布隆过滤器的配置可以在表级别进行,具体操作如下:

创建表时配置

// Java 代码示例
Configuration config = HBaseConfiguration.create();
HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));
HColumnDescriptor columnDescriptor = new HColumnDescriptor(familyName);// 设置布隆过滤器类型为 ROW
columnDescriptor.setBloomFilterType(BloomType.ROW);// 设置布隆过滤器的误报率,例如 0.01 表示 1% 的误报率
columnDescriptor.setBloomFilterFalsePositiveChance(0.01f);
tableDescriptor.addFamily(columnDescriptor);
admin.createTable(tableDescriptor);

修改现有表的配置

// Java 代码示例
Configuration config = HBaseConfiguration.create();
Admin admin = ConnectionFactory.createConnection(config).getAdmin();
TableName tableName = TableName.valueOf(tableName);
HColumnDescriptor columnDescriptor = new HColumnDescriptor(familyName);// 获取表的描述符
HTableDescriptor tableDescriptor = admin.getTableDescriptor(tableName);// 设置布隆过滤器类型为 ROW
columnDescriptor.setBloomFilterType(BloomType.ROW);// 更新列族描述符
tableDescriptor.modifyFamily(columnDescriptor);
admin.modifyTable(tableName, tableDescriptor);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/50074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【NPU 系列专栏 2.8 -- 特斯拉 FDS NPU 详细介绍 】

请阅读【嵌入式及芯片开发学必备专栏】 文章目录 特斯拉 NPU 芯片介绍FSD(Full Self-Driving)芯片 简介FSD主要特点FSD 详细参数FSD 应用场景特斯拉 Hardware 3.0 芯片 简介Hardware 3.0主要特点Hardware 3.0 详细参数Hardware 3.0应用场景特斯拉自研 NPU 的优势优化设计高度…

【数学建模】——matplotlib简单应用

目录 1.绘制带有中文标签和图例的正弦和余弦曲线 2. 绘制散点图 1.修改散点符号与大小 2.修改颜色 3.绘制饼状图 4.在图例中显示公式 5.多个图形单独显示 6.绘制有描边和填充效果的柱状图 7.使用雷达图展示学生成绩 8.绘制三维曲面 9.绘制三维曲线 10.设置…

定制化即时通讯企业级移动门户解决方案,WorkPlus IM系统让工作事半功倍

随着移动设备的普及和移动办公的兴起&#xff0c;企业越来越需要一种定制化的即时通讯企业级移动门户解决方案来提高工作效率和团队协作效果。WorkPlus IM系统作为一种创新的解决方案&#xff0c;为企业提供了一个个性化定制、高度安全和高效便捷的移动门户平台。本文将对定制化…

BFF:优化前后端协作设计模式

BFF&#xff1a;优化前后端协作设计模式 BFF是什么 BFF即 Backends For Frontends (服务于前端的后端)。是一种介于前端和后端之间一种重要的通信设计模式。它旨在解决前端与后端协作中的复杂性问题。 背景 行业背景&#xff1a;传统前端应用&#xff08;如Web应用、移动应…

微服务-MybatisPlus下

微服务-MybatisPlus下 文章目录 微服务-MybatisPlus下1 MybatisPlus扩展功能1.1 代码生成1.2 静态工具1.3 逻辑删除1.4 枚举处理器1.5 JSON处理器**1.5.1.定义实体****1.5.2.使用类型处理器** **1.6 配置加密&#xff08;选学&#xff09;**1.6.1.生成秘钥**1.6.2.修改配置****…

网络安全防御【IPsec VPN搭建】

目录 一、实验拓扑图 二、实验要求 三、实验思路 四、实验步骤&#xff1a; 修改双机热备的为主备模式&#xff1a; 2、配置交换机LSW6新增的配置&#xff1a; 3、防火墙&#xff08;FW4&#xff09;做相关的基础配置&#xff1a; 4、搭建IPsec VPN通道 &#xff08;1…

Java代码基础算法练习-求杨辉三角第n行的值-2024.07.27

任务描述&#xff1a; 给定一个非负整数n&#xff0c;生成「杨辉三角」的第n行。&#xff08;1<n<10&#xff09;在「杨辉三角」中&#xff0c;每 个数是它左上方和右上方的数的和。 &#xff08;提示&#xff0c;第一列数值为1&#xff0c;如数组下标用i,j表示&#xf…

独占电脑资源来执行一个应用

1. 背景 在人工智能时代&#xff0c;随着神经网络的发展&#xff0c;训练人工智能模型需要越来越多的硬件资源&#xff0c;例如&#xff0c;利用10万条棋局数据、使用一台PC电脑、完整地训练一次确定性神经网络五子棋模型&#xff0c;需要花费一年半的时间。随着训练数据的增长…

APP逆向 day23司小宝逆向

一.前言 今天也是讲最后一个基础知识点了&#xff0c;ptrace占坑&#xff0c;这个也算是一个坑&#xff0c;今天通过这个案例和大家讲一下&#xff0c;今天这个案例我们来整验证码登录&#xff0c;版本选择4.7.8 二.抓包分析 抓包发现&#xff0c;请求头里的东西通过改包发现…

Spring Boot:图书管理系统(一)

1.编写用户登录接口 代码&#xff1a; package com.example.demo;import jakarta.servlet.http.HttpSession; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotatio…

技术成神之路:设计模式(九)备忘录模式

介绍 备忘录模式&#xff08;Memento Pattern&#xff09;是一种行为设计模式&#xff0c;它允许在不破坏封装性的前提下捕获和恢复对象的内部状态。通过备忘录模式&#xff0c;可以在程序运行过程中保存和恢复对象的某个状态&#xff0c;从而实现“撤销”等功能。 1.定义 备忘…

【BUG】已解决:UnicodeDecodeError: ‘utf-8’ codec can’t decode bytes in position 10

UnicodeDecodeError: ‘utf-8’ codec can’t decode bytes in position 10 目录 UnicodeDecodeError: ‘utf-8’ codec can’t decode bytes in position 10 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#x…

使用python内置的虚拟环境

在一台机器上安装了太多的第三方python库&#xff0c;它们依赖相同的库可能版本不同&#xff0c;就会造成某些第三方库崩溃&#xff0c;之前可以使用的库可能就会坏掉不能用了&#xff0c;所以可以使用虚拟环境运行不同的程序&#xff0c;python有内置的虚拟环境&#xff1b; …

前端八股文 promise async await 的理解

promise是什么 Promise 是异步编程的一种解决方案&#xff0c;比传统的解决方案——回调函数和事件——更合理和更强大。 目的 解析 吴优编程 &#xff08;解决异步编程中的嵌套问题的&#xff0c;将嵌套的格式 用peomise 写成同步&#xff09; promise.then() 是成功后继…

Cocos Creator2D游戏开发(4)-飞机大战(2)-编辑器界面

编辑器几个重要板块 参考: https://docs.cocos.com/creator/3.8/manual/zh/editor/ (1) 场景编辑器: 仅看2D视图: 按钮作用依次是: 平移, 旋转,缩放,矩形变换,增量吸附工具,最后三个,前俩是变换工具,最后一个是布局组件 矩形变换: 中心点和锚点切换 以后用到慢慢整吧! (2)层…

AI服务器产业链研究分析

AI服务器产业链初探 一、AI服务器的技术架构与构成 AI服务器的主要构成包括&#xff1a; 芯片种类丰富&#xff0c;包括X86、ARM、MIPS等架构的CPU&#xff0c;以及GPU、FPGA、ASIC和NPU等。 内存&#xff1a;DRAM、HBM&#xff08;高带宽存储&#xff09;。 本地存储&#…

前端开发调试工具推荐分类整理

具体前往&#xff1a;前端调试工具分类整理汇总

黑马Java零基础视频教程精华部分_6_字符串

系列文章目录 文章目录 系列文章目录前言一、API是什么&#xff1f; API帮助文档案例&#xff1a;API文档练习Step1&#xff1a;查找文档中Scanner内容。Step2&#xff1a;学习文档中Scanner内容。 二、字符串String类1、String概述总结&#xff1a; 创建String对象的两种方式2…

java学习--String类StringBuffer类StringBuilder类

String类简介 关系图&#xff1a; value不可修改的是value指向的地址&#xff0c;因为可以value为一个数组&#xff0c;而数组名其实就相当于一个指针&#xff0c;指向着一块地址&#xff0c;然后在指向的地址里存放相应的值&#xff0c;值可以任意是什么&#xff0c;但是地址不…

RedHat Enterprise Linux 7 YUM源(本地/网络源)配置详解

目录 一、挂载 二、建立本地源 三、建立网络源 四、验证可行性 一、挂载 ——将光盘挂载到 /mnt 下 当/mnt中有如图内容时&#xff0c;即挂载成功 若挂载光驱/dev/sr0时报错&#xff1a;mount: no medium found on /dev/sr0 解决措施&#xff1a;查看该设备状态是否全部勾选…