刀太锋利,人人都喜欢。人太锋利,没人会喜欢。
一 使用背景
当判断一个数在不在大一堆数据中 我们可以使用一个set集合 然后用 contains 就可以判断这个数据在不在里面了,但是随着数据量的增大, 除非你的内存足够大,当数据大过你的内存的时候 这个时候你想判断这个数在不在你这个数据集合中 你应该怎么做,这个时候 布隆过滤器应运而生。
二 数据结构
布隆过滤器是一个叫“布隆”的人提出的,它本身是一个很长的二进制向量,既然是二进制的向量,那么显而易见的,存放的不是0,就是1。
类比成这个样子
现在需要添加一个数据:
我们通过某种计算方式,比如Hash1,计算出了Hash1(数据)=5,我们就把下标为5的格子改成1,就像下面这样:
我们又通过某种计算方式,比如Hash2,计算出了Hash2(数据)=9,我们就把下标为9的格子改成1,就像下面这样:
还是通过某种计算方式,比如Hash3,计算出了Hash3(数据)=2,我们就把下标为2的格子改成1,就像下面这样:
其实,布隆过滤器本身是没有存储数据本身的 只是记了一个标识 这个时候如果别的数据进来了 进行哈希 发现这几个位置都是1 了 所有判断这个数据已经存在了 但是也有可能这个数据是别的数据变成1 的 这个时候就是误判了。
所以 他过来一个数据 只能判断这个数据一定不存在,不能判断是否存在 。
三 实现
java 实现 可以直接用guava 里面的包实现
- 导包
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
- 使用
@Test
void guavaBloomTest() {
// 布隆过滤器
BloomFilter<Integer> filter = BloomFilter.create(
Funnels.integerFunnel(),
1500,
0.01);
filter.put(1);
System.out.println(filter.mightContain(1));
}
这对于单机的来说是可以的 如果是分布式的话 redis 有提供布隆过滤器的解决方案
参考 https://www.cnblogs.com/CodeBear/p/10911177.html
布隆过滤器用作在redis 缓存穿透的场景是:
在请求之前将数据库的数据放在布隆过滤器中 这个时候能过滤掉数据库中肯定没有的 如果有的话 接下来该走redis 走redis redis 中没有的话 就请求数据库