首页 > 其他分享 >什么是布隆过滤器,实现原理是什么?

什么是布隆过滤器,实现原理是什么?

时间:2024-08-23 18:24:12浏览次数:11  
标签:redisson 什么 元素 布隆 哈希 过滤器 bloomFilter

背景介绍

在互联网中,我们经常遇到需要在大量数据中判断目标数据是否存在的情况。例如,在网络爬虫中,我们需要判断某个网址是否已经被访问过。为了实现这一功能,通常需要使用一个容器来存储已访问过的网址。如果将这些数据直接存储在磁盘中,每次判断都要进行磁盘查询,这将导致大量的IO操作,效率较低。因此,我们希望将这些数据保存在内存中。在数据量较小的情况下,可以使用Redis来存储这些数据。但是,当数据量超过上千万时,将会消耗几GB甚至几十GB的内存空间。然而,对于仅需要记录数据是否存在的情况而言,这样使用大量内存显然是浪费的。为了解决这个问题,我们可以使用布隆过滤器(Bloom Filter)。布隆过滤器是一种占用空间少且时间效率高的工具。

布隆过滤器原理

什么是布隆过滤器?

布隆过滤器是一种空间效率高和时间效率高的概率型数据结构,用于判断某个元素是否在一个集合中。它通过多个哈希函数将元素映射到一个位数组中,虽然能快速判断元素是否存在,但有一定的误判率,即可能会误认为元素存在,但不会漏掉实际存在的元素。

简单点,你可以认为,布隆过滤器确实是一个很长的二进制向量(位数组)和一系列哈希函数的组合~

布隆过滤器的原理很简单:

当一个元素被添加到集合中时,它会通过m个哈希函数映射到位数组中的m个位置,并将这些位置的值设置为 1。在检查元素是否在集合中时,检查这些位置是否全为 1。如果其中有任何一个位置为 0,则该元素一定不在集合中;如果所有位置均为 1,则该元素可能在集合中

 举个例子:

假设现在有3个哈希函数,和一个8位的bit数组。元素a和b,都经过三次哈希函数生成三个哈希值,并映射到位数组的不同的位置,并设置为1。元素a映射的位置是(0,3,7),元素b映射的位置是(2,5,7).

如果一个元素c过来,我们检查它映射后的三个位置是否全是1,就可以判断元素C是否在当前集合中了。

其实我们可以发现,元素a和元素b映射的位置7都是1,也就是说,位置是可能重叠的。假设当前集合已经有a和b了,但是呢一个元素c过来,它映射的位置为(0,2,7),这时候,它的所有位置都是1,布隆过滤器是认为它可能在集合中,但是我们看到元素c是不在当前集合中的

也是就说,布隆过滤器是可能存在误判的,通俗点说就是假阳性

布隆过滤器的优点和缺点

布隆过滤器的缺点,其实就是,存在一定误判。

要降低误判率的话,我们可以:

  • 增加位数组的大小:增大位数组的长度可以减少每个位的填充率,从而降低假阳性率。较大的位数组可以容纳更多的元素,并且哈希值的碰撞几率减少。

  • 增加哈希函数的数量:使用更多的哈希函数可以进一步分散哈希映射,降低假阳性率。

  • 使用分级布隆过滤器:在布隆过滤器前使用一个较小的布隆过滤器作为初步过滤器,只有在初步过滤器确认元素可能存在时,才使用主要布隆过滤器,这可以减少对主要布隆过滤器的查询次数。

而布隆过滤器的优点也很明确,它的空间效率和查询效率,相对与其他一般算法,都有明显优势。正所谓鱼和熊掌,不可兼得,但是它居然不一样,空间和时间效率都不错

确切地说,布隆过滤器的高效和低空间复杂度归功于其使用的哈希函数和位数组。它利用多个哈希函数将数据映射到一个固定大小的位数组中,减少了需要存储的数据量,从而降低了空间复杂度。由于它是基于位操作的,查找操作也非常快,这使得它在处理大量数据时表现出高效性

布隆过滤器的经典使用场景

缓存穿透 

布隆过滤器,常常跟我们讨论的缓存穿透出现。它是最经典的使用场景。

缓存穿透保护:在分布式缓存系统中,布隆过滤器可以用来防止缓存穿透。通过在缓存前面加一个布隆过滤器,可以有效地阻止不存在的数据请求直接到达后端数据库,从而减少数据库负载和提高系统性能。

恶意网址检测

布隆过滤器可以用于网络安全中,例如检测恶意网址。通过将已知的恶意网址存储在布隆过滤器中,可以快速判断一个网址是否可能是恶意的。

防止消息重复消费

防止消息重复消费:布隆过滤器还可以用于防止MQ消息重复消费。比如说,我们在发送消息时可以对每个消息设置唯一的key,然后呢,在消费者消费处理时,利用布隆过滤器对消息的key检索。如果不存在则进行消费,然后插入布隆过滤器,如果存在则说明消息已经消费过。

但是呢,由于布隆过滤的假阳性,一般要求集合数据库存储已处理消息ID,来进一步减少重复消费的风险。

在消息量大、内存空间有限的情况下,使用布隆过滤器是个很不错的选择。

布隆过滤器可以用于网络安全中,例如检测恶意网址。通过将已知的恶意网址存储在布隆过滤器中,可以快速判断一个网址是否可能是恶意的。

使用 Google Guava库中的布隆过滤器 

使用Google Guava库中的布隆过滤器(Bloom Filter)功能展示如何创建一个布隆过滤器,并如何使用它来检查元素是否可能存在于集合中。

  • pom.xml中添加依赖:

<dependencies>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>30.1-jre</version> <!-- Use the latest version -->
    </dependency>
</dependencies>
  • 编写Java代码来创建和使用布隆过滤器:

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;

public class BloomFilterExample {
    public static void main(String[] args) {
        // 初始化布隆过滤器
        // 预期插入的元素数量
        long expectedInsertions = 10000L;
        // 期望的误报率
        double fpp = 0.03; // 3%的误报率

        // 使用Funnels.stringFunnel()来处理String类型的数据
        BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), expectedInsertions, fpp);

        // 插入元素
        bloomFilter.put("element1");
        bloomFilter.put("element2");
        // ... 可以继续插入其他元素

        // 检查元素是否可能存在于集合中
        boolean mightContainElement1 = bloomFilter.mightContain("element1");
        System.out.println("Element1 might be present: " + mightContainElement1); // 应该输出 true

        boolean mightContainElement3 = bloomFilter.mightContain("element3");
        System.out.println("Element3 might be present: " + mightContainElement3); // 可能输出 true 或 false,取决于误报率

        // 注意:布隆过滤器可能会产生误报(false positives),但不会产生误报(false negatives)
        // 如果 mightContain 返回 false,那么该元素肯定不在集合中
        // 如果 mightContain 返回 true,那么该元素可能在集合中,但也可能不在
    }
}

 使用 Redisson中的布隆过滤器

 

使用 Redisson 创建布隆过滤器,插入元素,并检查某个元素是否存在。

  • pom.xml 文件中添加 Redisson 依赖:

<dependencies>
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
        <version>3.16.1</version> <!-- 使用最新版本 -->
    </dependency>
</dependencies>
  • 编写代码来创建布隆过滤器,插入元素,并检查元素:

import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

public class RedissonBloomFilterExample {

    public static void main(String[] args) {
        // 配置 Redisson 客户端
        Config config = new Config();
        config.useSingleServer()
              .setAddress("redis://127.0.0.1:6379"); // 替换为你的 Redis 服务器地址

        // 创建 Redisson 客户端实例
        RedissonClient redisson = Redisson.create(config);

        // 创建布隆过滤器
        // 注意:这里的名称 "myBloomFilter" 是布隆过滤器的唯一标识,你可以根据需要更改
        RBloomFilter<String> bloomFilter = redisson.getBloomFilter("myBloomFilter");

        // 初始化布隆过滤器,设置预期插入的元素数量和误报率
        bloomFilter.tryInit(10000L, 0.03);

        // 插入元素
        bloomFilter.add("码");
        bloomFilter.add("道");

        // 查找元素
        boolean mightContainYi = bloomFilter.contains("易");
        System.out.println("布隆过滤器中可能包含'易':" + mightContainYi);

        // 关闭 Redisson 客户端
        redisson.shutdown();
    }
}

注意:由于布隆过滤器的特性,contains 方法返回 true 并不意味着元素一定存在,而返回 false 则意味着元素一定不存在。 

 

对于 bloomFilter.tryInit(10000L, 0.03); 的参数设置,应根据实际业务给出。

标签:redisson,什么,元素,布隆,哈希,过滤器,bloomFilter
From: https://blog.csdn.net/2301_76166241/article/details/141472313

相关文章

  • 织梦DedeCMS幻灯片调用图片为什么显示模糊
    很多使用织梦程序做网站的时候遇到一个问题就是dedecms网站首页幻灯片调用的是文章缩略图,如果我们实际图片宽高比例和幻灯片的比例相差太大的话,那么在首页显示的幻灯片图片就会自动拉伸变的模糊,这个看起来确实是一个比较影响用户体验的问题,下面就给大家分析一下解决这个问题的两个......
  • 帝国cms安全设置是什么
    帝国CMS的安全设置主要包括以下几个方面:强密码:确保管理员密码足够强大,不易被猜测或暴力破解。目录和脚本文件权限:设置合理的文件和目录权限,例如将 e/data/ 和 e/upload/ 目录的权限设置为777,以确保帝国CMS可以正常读写数据。启用安全模式:启用帝国CMS的安全......
  • 织梦dede:php标签是什么
    {dede:php} 标签是织梦CMS(DedeCMS)中的一个特殊标签,用于在模板文件中嵌入PHP代码。这个标签允许开发者在织梦CMS的模板中直接编写PHP代码,从而实现更灵活的逻辑处理。用法概述标签语法:开始标签:{dede:php}结束标签:{/dede:php}基本用法:在 {dede:php} 和 {/de......
  • 云渲染的三个条件是指什么!哪三点最重要!
    云渲染技术以其灵活性和效率,让创意人士和企业无论身处何地,都能通过网络接入强大的远程服务器,轻松完成复杂的图形渲染任务,但要发挥其魔力,我们得满足一些关键条件。一、网络连接:云渲染的桥梁首先,高速且稳定的网络连接是云渲染成功的基石。想象一下,如果网络连接时断时续,你的渲染任......
  • (装备篇)去参加马拉松需要带些什么 【跑长跑要带哪些东西】
    长跑,一项考验耐力和意志的运动,不仅需要良好的体能基础,还需要充分的准备工作。以下是一些长跑前应该做的准备,以及推荐携带的跑步装备。首先,跑鞋的选择至关重要。一双合适的跑鞋能够提供足够的支撑和缓冲,减少运动对膝盖和脚踝的冲击。同时,运动袜也是不可忽视的细节,应选择透气、......
  • 什么?!90%的ThreadLocal都在滥用或错用!
    最近在看一个系统代码时,发现系统里面在使用到了ThreadLocal,乍一看,好像很高级的样子。我再仔细一看,这个场景并不会存在线程安全问题,完全只是在一个方法中传参使用的啊!(震惊)难道是我水平太低,看不懂这个高级用法?经过和架构师请教和确认,这完全就是一个ThreadLocal滥用的典型案......
  • ETL数据集成丨为什么没有做好ETL的BI工具最终都会失败?
    随着数字化转型,企业越来越重视数据的价值和利用。商业智能(BusinessIntelligence,BI)作为一种数据分析和决策支持的重要工具,被广泛应用于各行各业。然而,对于BI项目的成功实施,ETL(Extract,Transform,Load)过程的重要性不容忽视。ETL作为BI项目的基础,如果缺乏或不完善,往往会导致BI项目......
  • 为什么通过clear_refs可以使进程触发缺页?
    平台ARM64Linux6.10作者[email protected]背景最近在学习Linux的缺页异常时突然奇想,在不进行内存换出的情况下,如何让进程再次触发缺页?基于对ARMv8的理解,它的MMU的页表项中有个AF位,当AF为0时,当访问到对应的虚拟页时,会触发缺页。如果AF位为0,当访问到对应的虚拟页时......
  • 《离了我,你不能作什么》歌词
    《离了我,你不能作什么》歌词人间悲伤幻变多人生充满苦楚人能够作些什么人一生转眼就过人间悲伤幻变多人生充满苦楚人能够作些什么人一生转眼就过相信我离了我你不能作什么相信我离了我你不能作什么相信我离了我你不能作什么离了我你不能作什么丧失的我必寻找......
  • 为什么录屏没有声音?教你三招,解决系统与麦克风声音录制技巧
    电脑录屏声音同步技巧:系统与麦克风声音录制在游戏录制和微课制作中,音画同步是保证观众体验的关键因素。无论是紧张刺激的游戏解说,还是知识传递的微课讲解,清晰同步的声音都能让内容更加生动,更能吸引观众的注意力。然而,许多初学者在进行电脑录屏时常常会遇到声音录制不同步的问......