大佬教程收集整理的这篇文章主要介绍了面试官问:什么是布隆过滤器?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
布隆过滤器是一种由位数组和多个哈希函数组成概率数据结构,返回两种结果 可能存在 和 一定不存在。
布隆过滤器里的一个元素由多个状态值共同确定。位数组存储状态值,哈希函数计算状态值的位置。
根据它的算法结构,有如下特征:
比如下面,X,Y,Z 分别由 3个状态值共同确定元素是否存在,状态值的位置通过3个哈希函数分别计算。
关于误判概率,因为每个位的状态值可能同时标识多个元素,所以它存在一定的误判概率。如果位数组满,当判断元素是否存在时,它会始终返回true
,对于不存在的元素来说,它的误判率就是100%。
那么,误判概率和哪些因素有关,已添加元素的数量,布隆过滤器长度(位数组大小),哈希函数数量。
根据维基百科推理误判概率 (P_{fp}) 有如下关系:
由此可以得到,当添加元素数量为0时,误报率为0;当位数组全都为1时,误报率为100%。
不同数量哈希函数下,$ P_{fp}$ 和 $ n$ 的关系如下图:
根据误判概率公式可以做一些事
当 (n) 添加元素和 (P_{fp})误报概率确定时,(m) 等于:
当 (n) 和 (P_{fp}) 确定时,(k) 等于:
当 (n) 和 (m) 确定时,(k) 等于:
使用布隆过滤器前,我们一般会评估两个因素。
很多布隆过滤工具都提供了预期添加数量和误判概率配置参数,它们会根据配置的参数计算出最佳的长度和哈希函数数量。
Java中有一些不错的布隆过滤工具包。
Guava
中 BloomFilter
。redisson
中 RedissonBloomFilter
可以redis 中使用。看下 Guava
中 BloomFilter
的简单实现,创建前先计算出位数组长度和哈希函数数量。
static <T> BloomFilter<T> create(
Funnel<? super T> funnel, long expectedInsertions, double fpp, Strategy strategy) {
/**
* expectedInsertions:预期添加数量
* fpp:误判概率
*/
long numBits = optimalNumOfBits(expectedInsertions, fpp);
int numHashFunctions = optimalNumOfHashFunctions(expectedInsertions, numBits);
try {
return new BloomFilter<T>(new BitArray(numBits), numHashFunctions, funnel, strategy);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Could not create BloomFilter of " + numBits + " bits", e);
}
}
根据最佳布隆过滤器长度公式,计算最佳位数组长度。
static long optimalNumOfBits(long n, double p) {
if (p == 0) {
p = Double.MIN_VALUE;
}
return (long) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));
}
根据最佳哈希函数数量公式,计算最佳哈希函数数量。
static int optimalNumOfHashFunctions(long n, long m) {
return Math.max(1, (int) Math.round((double) m / n * Math.log(2)));
}
在redisson
中 RedissonBloomFilter
计算方法也是一致。
private int optimalNumOfHashFunctions(long n, long m) {
return Math.max(1, (int) Math.round((double) m / n * Math.log(2)));
}
private long optimalNumOfBits(long n, double p) {
if (p == 0) {
p = Double.MIN_VALUE;
}
return (long) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));
}
设想一个手机号去重场景,每个手机号占用22 Byte
,估算逻辑内存如下。
expected | HashSet | fpp=0.0001 | fpp=0.0000001 |
---|---|---|---|
100万 | 18.28MB | 2.29MB | 4MB |
1000万 | 182.82MB | 22.85MB | 40MB |
1亿 | 1.78G | 228.53MB | 400MB |
注:实际物理内存占用大于逻辑内存。
误判概率 (p) 和已添加的元素 (n),位数组长度 (m),哈希函数数量 (k) 关系如下:
维护一个哈希过弱密码列表。当用户注册或更新密码时,使用布隆过滤器检查新密码,检测到提示用户。
维护一个哈希过垃圾邮件地址列表。当用户接收邮件,使用布隆过滤器检测,检测到标识为垃圾邮件。
使用布隆过滤器来查找钓鱼网站数据库中是否存在某个网站的 URL。
缓存穿透是指查询一个根本不存在的数据,缓存层和数据库都不会命中。当缓存未命中时,查询数据库
一个典型的攻击,模拟大量请求查询不存在的数据,所有请求落到数据库,造成数据库宕机。
其中一种解决方案,将存在的缓存放入布隆过滤器,在请求前进行校验过滤。
对于千万亿级别的数据来说,使用布隆过滤器具有一定优势,另外根据业务场景合理评估预期添加数量和误判概率是关键。
参考
https://en.wikipedia.org/wiki/Bloom_filter
https://hur.st/bloomfilter
以上是大佬教程为你收集整理的面试官问:什么是布隆过滤器?全部内容,希望文章能够帮你解决面试官问:什么是布隆过滤器?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。