浅谈布隆过滤器

1. 问题情景

如果面试官问你,一个网站有 100 亿 url 存在一个黑名单中,每条 url 平均 64 字节。问这个黑名单要怎么存?若此时随便输入一个 url,如何判断该 url 是否在这个黑名单中?

对于第一个问题,如果把黑名单看成一个集合,将其存在 hashmap 中,貌似太大了,需要 640G,明显不科学。

那该怎么办?ok,现在该介绍今天的主角了 —— 布隆过滤器就可以解决这样的问题。

首先,布隆过滤器是什么?维基百科是这样解释的:

布隆过滤器(英语:Bloom
Filter)是1970年由布隆提出的。它实际上是一个很长的二进制矢量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

官方说法看下就好,如果不理解没关系,其实不会难,下面我们讲人话慢慢来。

2. 具体介绍

布隆过滤器实际上是一个很长的二进制矢量和一系列随机映射函数。

「很长的二进制矢量」:这是一个长度很长的数组,什么类型的数组呢?bit 类型的数组,也是我们说的「位」,(1Byte = 8bit,1KB = 1024Byte)。

「一系列随机映射函数」:有多个哈希函数。那什么是哈希函数呢?JDK 里面有计算得到哈希值的方法,那就是一个哈希函数。

布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难

这个不就可以解决我们最开始的问题吗?那它是怎么解决的呢?

3. 解决过程

下面我说下大体的过程,细节部分可先不理解,重要的是明白流程,细节我后面补充。

假设,bit 类型数组的长度为 m,每个元素值为 0,有 k 个哈希函数。

首先,当输入一个 url 的时候,此时这个 url 会经过 k 个哈希函数处理,得到多个哈希值(v1,v2,…,vk)。之后得到这些哈希值对应在数组的下标位置,最后将这些下标的元素都置为 1。

那么如何判断一个 url 在黑名单里面呢?输入一条 url,它经过上述处理之后,会得到多个数组的下标位置。如果这些下标的元素值都已经为 1 了,说明该在黑名单里面,否则不在。

总体就是这样的流程,下面说下大家可能存在的疑问:

1、bit 类型的数组如何构建

2、得到 v1,v2,…,vk 这些哈希值后,如何得到其在数组的下标位置,并将其设置为 1 呢?

两个问题我一起说下,Java 里面没有 bit 这样的类型,怎么构建呢?—— 不难,我们可以使用 int,一个 int 是 32 位。

//创建了一个 100 * 32bit 的数组
int[] arr = new int[100]; 
// 代表 bit 数组 0-31 位的元素
arr[0];

因此上面再会说「分别将这些哈希值除以数组的长度 m,和对 m 取模,得到这些哈希值对应在数组的下标位置」。

具体我们可以拿一个哈希值 data 来举个栗子,假设 int 数组长度为 100。

void Set(int data) {
       // ByteNO 是表示在 table 数组中那个元素
       int ByteNo = data / 32;
       // bitNo 是表示在 32 位 bit 中哪个 bit 位。
       int BitNo = data % 32;
       // 置 1
       _table[ByteNo] |= (1 << BitNo); 
   }

4. 使用效果

最开始我们提到,如果将 100 亿 url 放到 HashMap 中需要 640GB,那么使用布隆过滤器后又需要多少空间呢?答案是约等于 23 GB。相比之下,这个空间大小是不是就可以接受很多了。

5. 缺点

布隆过滤器有宁可错杀一百,也不能放过一个的性质。讲人话就是属于黑名单的 url 一定能够正确判断它在黑名单中,但不属于黑名单中的 url 也可能会被认为在黑名单中,存在一定的失误率。

至于失误率要保持在多少,数组长度,哈希函数的个数分别要设置多少就需要根据实际情况来选择了,网上有对应的数学公式计算,这里就不展开讲了。

参考:
https://blog.csdn.net/wenqiang1208/article/details/76724338

PS:本文原创发布于微信公众号「不只Java」,后台回复「Java」,送你 13 本 Java 经典电子书。公众号专注分享 Java 干货、读书笔记、成长思考。

不只Java

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redisson布隆过滤器是基于Redis实现的Java分布式布隆过滤器。它可以在多个JVM节点或其他进程中通过相同的KEY获取到布隆过滤器布隆过滤器的主要功能是判断某个元素是否存在于容器中,因此非常适合解决缓存穿透问题和检查数据是否重复的场景。使用Redisson布隆过滤器时,需要单独开一个定时任务来初始化布隆过滤器的数据,并在删除或更新数据时重新刷新布隆过滤器。虽然使用布隆过滤器可能稍显麻烦,但可以使用Redis的Set类型来替代。\[1\]\[2\] 在代码示例中,可以看到使用Redisson布隆过滤器的示例代码。首先通过redisson.getBloomFilter方法获取布隆过滤器实例,然后使用tryInit方法初始化布隆过滤器的容量和误差率。接下来可以使用add方法向布隆过滤器中添加元素,使用contains方法判断元素是否存在于布隆过滤器中。\[2\]\[3\] 总结来说,Redisson布隆过滤器是一种解决缓存穿透和检查数据重复的有效工具,但在使用时需要注意初始化和刷新布隆过滤器的操作。 #### 引用[.reference_title] - *1* *2* *3* [从头开始学Redisson--------布隆过滤器](https://blog.csdn.net/yanluandai1985/article/details/104848454)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值