1、什么是布隆过滤器
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
布隆过滤器可以理解为一个set集合,我们可以通过add往里面添加元素,通过contains来判断是否包含某个元素。由于本文讲述布隆过滤器时会结合Redis来讲解,因此类比为Redis中的Set数据结构会比较好理解,而且Redis中的布隆过滤器使用的指令与Set集合非常类似。
布隆过滤器的优点:
时间复杂度低,增加和查询元素的时间复杂为O(N),(N为哈希函数的个数,通常情况比较小)
保密性强,布隆过滤器不存储元素本身
存储空间小,如果允许存在一定的误判,布隆过滤器是非常节省空间的(相比其他数据结构如Set集合)
布隆过滤器的缺点:
有点一定的误判率,但是可以通过调整参数来降低
无法获取元素本身
很难删除元素
2、布隆过滤器的使用场景
布隆过滤器可以告诉我们 “某样东西一定不存在或者可能存在”,也就是说布隆过滤器说这个数不存在则一定不存,布隆过滤器说这个数存在可能不存在(误判,后续会讲),利用这个判断是否存在的特点可以做很多有趣的事情。
解决Redis缓存穿透问题
邮件过滤,使用布隆过滤器来做邮件黑名单过滤
对爬虫网址进行过滤,爬过的不再爬
解决新闻推荐过的不再推荐(类似抖音刷过的往下滑动不再刷到)
HBase\RocksDB\LevelDB等数据库内置布隆过滤器,用于判断数据是否存在,可以减少数据库的IO请求
3、布隆过滤器的原理
3.1 数据结构
布隆过滤器它实际上是一个很长的二进制向量和一系列随机映射函数。以Redis中的布隆过滤器实现为例,Redis中的布隆过滤器底层是一个大型位数组(二进制数组)+多个无偏hash函数。
在代码中加入以下配置:
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
@Data
public class RedissonConfiguration {
private String host;
private String port;
private String password;
@Bean
public Redisson redisson() {
String address = "redis://".concat(host).concat(":").concat(port);
Config config = new Config();
SingleServerConfig singleServer = config.useSingleServer();
singleServer.setAddress(address)
.setConnectionPoolSize(30)
.setConnectionMinimumIdleSize(10);
if (Func.isNotBlank(password)) {
singleServer.setPassword(password);
}
return (Redisson) Redisson.create(config);
}
}
Redisson使用:
private static final String BOOLFILTER_KEY = "boolFilter:user";
@Resource
private RedissonClient redissonClient;
@Test
void contextLoads() {
// 根据BloomFilter名称获取BloomFilter过滤器
RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(BOOLFILTER_KEY);
// 设置预计插入的次数以及误判率
bloomFilter.tryInit(5000, 0.001);
// 向BloomFilter添加数据
bloomFilter.add("测试");
// 判断BloomFilter是否包含此项
bloomFilter.contains("测试");
}