布隆过滤器(Bloom Filter)

2023-09-14 12:47:04

一,布隆过滤器介绍

布隆过滤器(Bloom Filter)是一个很长的二进制向量(位图BitMap)和一系列随机映射函数(Hash函数)。它是一种数据结构,可以判断一个元素一定不在集合中可能存在于集合中。

优点:相比于传统的list、set、map等数据结构,它更高效、占用空间更少。
缺点:存在误判率

二,布隆过滤器原理

布隆过滤器是一个字节向量,初始值全部为0

1. 原理

当一个元素被加入集合时,通过K个hash函数将这个元素映射成一个位数组中的K个点,把它们置为1。

2. 检索元素

通过k个点位(Hash函数个数)的值进行判断。

  • k个点位中有任一为0,被检元素一定不存在
  • k个点位都是1,被检元素可能存在。

三,布隆过滤器设计

布隆过滤器存在误判率,在查找元素值都返回1的时候,我们没法确定该元素就一定存在,不过我们可以通过一些参数的设置来降低误判率。
假设:

M向量表的长度
K哈希函数的个数
N插入的元素个数
P误判率

在实际应用中,我们一般是可以给定N、P,然后计算出M、K。

1. 向量表的长度 M 计算

2. 哈希函数个数 K 计算

3. 哈希函数的选择

  • 常见应用比较广的hash函数有MD5,常用于签名认证和加密等。比如我们传文件时习惯对原文件内容计算它的MD5,生成128bit的整数,通常我们说的32位MD5,是转换为16进制后的32个字符。
  • MurmurHash相比较MD5,不太安全。但性能是MD5的几十倍。MurmurHash有多个版本,MurmurHash2,MurmurHash3。

我们可以选择MurmurHash2。

4. 注意

布隆过滤器不能删除元素,在布隆过滤器算法中会存在一个bit位被多个元素值覆盖的情况。

四,安装使用布隆过滤器

Redis 提供的 bitMap 可以实现布隆过滤器,但是需要自己设计映射函数和一些细节,这和我们自定义没啥区别。

Redis 官方提供的布隆过滤器到了 Redis 4.0 才正式登场。Redis 4.0 提供了插件功能,布隆过滤器作为一个插件加载到 Redis Server 中,给 Redis 提供了强大的布隆去重功能。

安装 RedisBloom

在已安装 Redis 的前提下,安装 RedisBloom,有两种方式:

1. 直接编译进行安装:

git clone https://github.com/RedisBloom/RedisBloom.git
cd RedisBloom
make     #编译 会生成一个rebloom.so文件
redis-server --loadmodule /path/to/rebloom.so   #运行redis时加载布隆过滤器模块
redis-cli    # 启动连接容器中的 redis 客户端验证

2. 使用Docker进行安装:

docker pull redislabs/rebloom:latest # 拉取镜像
docker run -p 6379:6379 --name redis-redisbloom redislabs/rebloom:latest #运行容器
docker exec -it redis-redisbloom bash
redis-cli

使用布隆过滤器

布隆过滤器基本指令:

  • bf.add 添加元素到布隆过滤器
  • bf.exists 判断元素是否在布隆过滤器
  • bf.madd 添加多个元素到布隆过滤器,bf.add 只能添加一个
  • bf.mexists 判断多个元素是否在布隆过滤器

上面使用的布隆过滤器只是默认参数的布隆过滤器,它在我们第一次 add 的时候自动创建。

Redis 还提供了自定义参数的布隆过滤器,bf.reserve 过滤器名 error_rate initial_size

  • error_rate:允许布隆过滤器的错误率,这个值越低过滤器的位数组的大小越大,占用空间也就越大
  • initial_size:布隆过滤器可以储存的元素个数,当实际存储的元素个数超过这个值之后,过滤器的准确率会下降

但是这个操作需要在 add 之前显式创建。如果对应的 key 已经存在,bf.reserve 会报错

127.0.0.1:6379> bf.reserve user 0.01 100
(error) ERR item exists
127.0.0.1:6379> bf.reserve topic 0.01 1000
OK

五,布隆过滤器部分源码

基于Redis位图(BitMap)实现的布隆过滤器的源码地址:

https://github.com/xqiangme/spring-boot-example/tree/master/spring-boot-redis-bloomFilter

向量表的长度 M 与 哈希函数个数 K 的计算

void CalcBloomFilterParam(uint32_t n, double p, uint32_t *pm, uint32_t *pk)
{
    /**
     *  n - Number of items in the filter  //要插入的元素个数
     *  p - Probability of false positives, float between 0 and 1 or a number indicating 1-in-p  //误判率
     *  m - Number of bits in the filter  //向量表的长度
     *  k - Number of hash functions  //哈希函数的个数
     *
     *  f = ln(2) × ln(1/2) × m / n = (0.6185) ^ (m/n)
     * m = -1*n*ln(p)/((ln(2))^2) = -1*n*ln(p)/(ln(2)*ln(2)) = -1*n*ln(p)/(0.69314718055995*0.69314718055995))
     *   = -1*n*ln(p)/0.4804530139182079271955440025
     * k = ln(2)*m/n
    **/

    uint32_t m, k, m2;

    // 计算指定假阳(误差)概率下需要的比特数(向量表长度)
    m =(uint32_t) ceil(-1.0 * n * log(p) / 0.480453); 	//向上舍入为最近的整数
    m = (m - m % 64) + 64;     // 8字节对齐

    // 计算哈希函数个数
    double double_k = (0.69314 * m / n); 
    k = round(double_k);    // 返回四舍五入整数值
    
    *pm = m;
    *pk = k;
    return;
}

六,布隆过滤器的应用

1. 黑名单校验
2. 快速去重
3. 爬虫URL校验
4. 解决Redis的缓存穿透问题(在Redis专栏会详细讲解)

七,布隆过滤器的优缺点

优点:

        1. 占用内存少,插入和查询速度快,时间复杂度都为 O(K)。

        2. 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势。

缺点:

        1. 存在误判率。

        2. 无法删除元素。

更多推荐

洁净室/净化车间:洁净等级划分及标准、检测方法及流程解读

无尘车间的发展与现代工业、尖端技术紧密的联系在一起。目前在生物制药、医疗卫生、食品日化、电子光学、能源、精密器械等行业运用已经相当的普遍且成熟。空气洁净度等级(aircleanlinessclass):洁净空间单位体积空气中,以大于或等于被考虑粒径的粒子最大浓度限值进行划分的等级标准。国内按空态、静态、动态对无尘车间进

MySQL详细案例 1:MySQL主从复制与读写分离

文章目录1.MySQL主从复制1.1使用场景1.2MySQL的复制类型1.3主从复制的作用1.4主从复制的工作过程1.5实现MySQL主从复制1.5.1前置准备1.5.2主服务器mysql配置1.5.3从服务器1mysql配置1.5.4从服务器2mysql配置1.5.5测试1.6主从复制的3种同步模式1.6.1异步复制

实时数仓混沌演练实践

一、背景介绍目前实时数仓提供的投放实时指标优先级别越来越重要,不再是单独的报表展示等功能,特别是提供给下游规则引擎的相关数据,直接对投放运营的广告投放产生直接影响,数据延迟或者异常均可能产生直接或者间接的资产损失。从投放管理平台的链路全景图来看,实时数仓是不可或缺的一环,可以快速处理海量数据,并迅速分析出有效信息,同时

Java JVM分析利器JProfiler 结合IDEA使用详细教程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、JProfiler是什么?二、我的环境三、安装步骤1.Idea安装JProfiler插件1.下载程序的安装包四、启动前言对于我们Java程序员而言,肯定需要对项目工程进行JVM监控分析,最终选择jprofiler,它可以远程链接,使用方便,

opencv图像像素类型转换与归一化

文章目录opencv图像像素类型转换与归一化1、为什么对图像像素类型转换与归一化2、在OpenCV中,`convertTo()`和`normalize()`是两个常用的图像处理函数,用于图像像素类型转换和归一化;(1)`convertTo()`函数用于将一个`cv::Mat`对象的像素类型转换为另一种类型。它的基本用法

第8章 MySQL的数据目录

8.1数据库和文件系统的关系像InnoDB、MyISAM这样的存储引擎都是把表存储在磁盘上的,而操作系统用来管理磁盘的又被称为文件系统,所以用专业一点的话来表述就是:像InnoDB、MyISAM这样的存储引擎都是把表存储在文件系统上的。当我们想读取数据的时候,这些存储引擎会从文件系统中把数据读出来返回给我们,当我们想写

公私钥非对称加密 生成和验证JSON Web Token (JWT)

前言这是我在这个网站整理的笔记,关注我,接下来还会持续更新。作者:神的孩子都在歌唱公私钥非对称加密生成和验证JSONWebToken什么是JSONWebToken(JWT)Java程序中生成和验证JWT代码解析什么是JSONWebToken(JWT)JSONWebToken(JWT)是一种轻量级的身份验证和授权机制,由

【Linux 之二】Ubuntu下开发环境的搭建(NFS \ SSH \ FTP \ Smba \ ...)

目前正在进行Linux相关项目的开发,而我的Linux开发是在Ubuntu(版本20.04)下进行的,为此需要搭建很多Linux相关的开发环境,方便工作的进行。这里主要是对各种开发环境的搭建做一个总结记录,方便后面查阅,也方便在Linux开发之路上遇到困难的各位同仁。好了,废话不多说,直接罗列各种开发环境的安装步骤等。

Java 多线程

目录线程相关概念线程基本使用1.继承Thread类,重写run方法示例代码程序示意图2.实现Runnable接口,重写run方法示例代码*应用案例代码理解3.继承Threadvs实现Runnable的区别4.多线程售票问题引出同步互斥问题5.线程终止代码示意图线程常用方法第一组示例代码第二组示例代码用户线程和守护线程示

Google Guava精讲(一)-Guava是什么?能做什么?

https://mvnrepository.com/artifact/com.google.guava/guava作为Java栈的测试工程师,在写代码时候会频繁遇到字符串处理、缓存、反射等问题,我们最常规的做法就是,为了使原生的JDK方法好用,通常是做了一层又一层封装,然后提供整个测试团队使用,而渐渐的就形成了自己的J

什么是葡萄酒结构,结构型葡萄酒好吗?

葡萄酒爱好者使用许多复杂的术语来描述葡萄酒的味道,有些是不言自明的,有些则有点模糊。如果你不是葡萄酒专家,你可能很难理解这个葡萄酒术语的全部含义。其中一个术语是葡萄酒结构,那么葡萄酒结构是什么意思呢?而结构酒是好东西吗?葡萄酒的结构是指葡萄酒的主要特征之间的相互作用,包括酒体、酒精度、酸度、单宁和甜度,葡萄酒的结构决定

热文推荐