1. 简介

布隆过滤器是防止缓存穿透的方案之一。布隆过滤器主要是解决大规模数据下不需要精确过滤的业务场景,如检查垃圾邮件地址,爬虫URL地址去重, 解决缓存穿透问题等。

布隆过滤器:在一个存在一定数量的集合中过滤一个对应的元素,判断该元素是否一定不在集合中或者可能在集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难

想详细了解的,可以查看我的另一篇博客Redis-缓存穿透/击穿/雪崩

2. guava 实现

google的guava工具类已经帮我们造好了轮子,通过实例来感受一下。

2.1 导入依赖

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
</dependency>

2.2 BloomFilterTest

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import lombok.extern.slf4j.Slf4j; /**
* 布隆过滤器简单实现
* @author ludangxin
* @date 2021/8/16
*/
@Slf4j
public class BloomFilterTest {
/**
* 预计要插入元素个数
*/
private static final int SIZE = 1000000;
/**
* 误判率
*/
private static final double FPP = 0.01;
/**
* 布隆过滤器
*/
private static final BloomFilter<Integer> BLOOMFILTER = BloomFilter.create(Funnels.integerFunnel(), SIZE, FPP); public static void main(String[] args) {
//插入数据
for (int i = 0; i < 1000000; i++) {
BLOOMFILTER.put(i);
}
int count = 0;
// 过滤判断
for (int i = 1000000; i < 3000000; i++) {
if (BLOOMFILTER.mightContain(i)) {
count++;
log.info(i + "误判了");
}
}
log.info("总共的误判数:" + count);
}
}

2.3 启动测试

如上代码,我们设置了0.01的误差,过滤判断时从1000000到3000000,误判了2 * 20000000 ≈ 20339 符合预期。

.....
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999004误判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999045误判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999219误判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999699误判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999753误判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999838误判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999923误判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999928误判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 总共的误判数:20339

2.4 小节

guava的工具包虽然好用,但是数据集是存储在jvm中的,分布式环境下依然没法使用。

3. redisson 实现

3.1 导入依赖

<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.16.1</version>
</dependency>

3.2 BloomFilterWithRedisson

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
* redisson 布隆过滤器实现
*
* @author ludangxin
* @date 2021/8/16
*/
@Slf4j
@RestController
@RequestMapping("bloomFilter")
@RequiredArgsConstructor
public class BloomFilterWithRedisson {
private final RedissonClient redissonClient; /**
* 预计要插入元素个数
*/
private static final long SIZE = 1000000L;
/**
* 误判率
*/
private static final double FPP = 0.01; /**
* 自定义布隆过滤器的 key
*/
private static final String BLOOM_FILTER_KEY = "bloomFilter"; /**
* 向布隆过滤器中添加数据, 模拟向布隆过滤器中添加10亿个数据
*/
@GetMapping
public void filter() {
// 获取布隆过滤器
RBloomFilter<Integer> bloomFilter = redissonClient.getBloomFilter(BLOOM_FILTER_KEY);
// 初始化,容量为100万, 误判率为0.01
bloomFilter.tryInit(SIZE, FPP);
// 模拟向布隆过滤器中添加100万个数据
for (int i = 0; i < SIZE; i++) {
bloomFilter.add(i);
}
int count = 0;
// 过滤判断
for (int i = 1000000; i < 3000000; i++) {
if (bloomFilter.contains(i)) {
count++;
log.info(i + "误判了");
}
}
log.info("size:" + bloomFilter.getSize());
log.info("总共的误判数:" + count);
}
}

3.3 启动测试

由于机器性能有限,又是单机环境,所以程序没有跑完。

但由此也可以看出,基于redis的布隆过滤器虽然解决了分布式问题,但是性能和guava bloomfilter没法比。

Redisson实战-BloomFilter的更多相关文章

  1. 别再用 Redis List 实现消息队列了,Stream 专为队列而生

    上回说到使用 Redis 的 List 实现消息队列有很多局限性,比如: 没有良好的 ACK 机制: 没有 ConsumerGroup 消费组概念: 消息堆积. List 是线性结构,想要查询指定数据 ...

  2. Redis HyperLogLog 是什么?这些场景使用它,让我枪出如龙,一笑破苍穹

    在移动互联网的业务场景中,数据量很大,我们需要保存这样的信息:一个 key 关联了一个数据集合,同时对这个数据集合做统计. 比如: 统计一个 APP 的日活.月活数: 统计一个页面的每天被多少个不同账 ...

  3. Redisson 分布式锁实战与 watch dog 机制解读

    Redisson 分布式锁实战与 watch dog 机制解读 目录 Redisson 分布式锁实战与 watch dog 机制解读 背景 普通的 Redis 分布式锁的缺陷 Redisson 提供的 ...

  4. Redis实战篇

    Redis实战篇 1 Redis 客户端 1.1 客户端通信 原理 客户端和服务器通过 TCP 连接来进行数据交互, 服务器默认的端口号为 6379 . 客户端和服务器发送的命令或数据一律以 \r\n ...

  5. redis(7)--redis应用实战

    问题1:哨兵模式下客户端应该连接哪个redis-server? 问题2:集群模式下为什么会有MOVED error Redis Java客户端介绍 已有的客户端支持 Redis Java客户端有很多的 ...

  6. 硬核 | Redis 布隆(Bloom Filter)过滤器原理与实战

    在Redis 缓存击穿(失效).缓存穿透.缓存雪崩怎么解决?中我们说到可以使用布隆过滤器避免「缓存穿透」. 码哥,布隆过滤器还能在哪些场景使用呀? 比如我们使用「码哥跳动」开发的「明日头条」APP 看 ...

  7. (转)国内外三个不同领域巨头分享的Redis实战经验及使用场景

    随着应用对高性能需求的增加,NoSQL逐渐在各大名企的系统架构中生根发芽.这里我们将为大家分享社交巨头新浪微博.传媒巨头Viacom及图片分享领域佼佼者Pinterest带来的Redis实践,首先我们 ...

  8. 【原】实战-Java如何使用Redis

    实战-Java如何使用Redis Redis的Client支持的语言非常丰富,如下: ActionScript Bash C C# C++ Clojure Common Lisp Crystal D ...

  9. Hbase 设计与开发实战

    Hbase 概述 大数据及 NoSQL 的前世今生 传统的关系型数据库处理方式是基于全面的 ACID 保证,遵循 SQL92 的标准表设计模式(范式)和数据类型,基于 SQL 语言的 DML 数据交互 ...

随机推荐

  1. bootstrap validate 验证插件

    1.需要引入bootstrapValidator.min.js 2.在需要验证的控件中添加 class="form-control" 3.js中写验证的方法 $('#psasave ...

  2. hdu 3306 Another kind of Fibonacci 矩阵快速幂

    参考了某大佬的 我们可以根据(s[n-2], a[n-1]^2, a[n-1]*a[n-2], a[n-2]^2) * A = (s[n-1], a[n]^2, a[n]*a[n-1], a[n-1] ...

  3. hadoop安装前的准备

    1.操作系统安装 2.hostname设定 3.hosts文件设定 4.ssh免密码登录 5.NTP时间同步设定 6.iptables永久关闭 7.selinux永久关闭

  4. python 两种排序方法 sort() sorted()

    python中有两种排序方法,list内置sort()方法或者python内置的全局sorted()方法 区别为: sort()方法对list排序会修改list本身,不会返回新list.sort()只 ...

  5. buu 内涵软件

    一.无壳. 并且是32位程序, 二.用ida静态调试一下. 这里我脑子发热啊,flag已经在眼前,活生生被我放跑了,靠,我直接搜索字符串,然后就一脸懵逼的,进入了很多不知名的函数,就炸了,看了wp才知 ...

  6. IDA,IDA PRO 产品介绍

    IDA理念这是我们在开发产品时竭尽全力遵循的理念--在此过程中,我们相信我们将开发出能够为您带来所需的可靠性.便利性和易用性的软件.没有什么能打败人脑因为我们知道一秒钟的洞察力仍然胜过百年的处理时间, ...

  7. Mysql常用语句整理

    把工作常用的mysql命令整理一下,省的用的时候在到处找 1.常用命令 1.1 登录 mysql -u root -p 1.2 生成随机数 若在 i<=R<=j 范围内生成随机数 FLOO ...

  8. css--filter(滤镜) 属性

    前言 前段时间找工作面试官问到一个问题,你如何将一个网页整体置灰?面试遇到这样的问题,一下束手无策,之前没有接触过这样的需求,因此没有回答上来,面试结束我才知道了这是考查对 CSS3 的新属性的了解. ...

  9. Java | Map集合

    Map集合 在现实生活中,有非常多的东西,是和另外一种东西对应的,并且还是唯一的,比如:身份证号与个人,个人与手机,一夫一妻...等,这种关系就是对应关系,又叫做映射.Java为这种数据类型提供了专门 ...

  10. VMware中的虚机如何挂载U盘

    1.将U盘插入到宿主机上. 2.在VM Client上,点击宿主机,右键,扫描存储设备(目的是为了发现新USB存储) 3.在需要的虚拟机上编辑配置,添加硬件,添加USB设备(如果不进行以上2个步骤,此 ...