布隆过滤器
作用
告诉你某个元素一定不存在或者可能存在,相比于传统的List、Set、Map等数据结构,它更高效、占用的控件更小。
数据结构
布隆过滤器是一个bit向量或者bit,如果我们要映射一个值到布隆过滤器中,我们㤇使用多个不同的哈希函数生成多个哈希值,并将每个生成的哈希值指向的bit位设置为1,如下baidu一词设置了三个位置为1
“tencent”一词,对应的情况
可以看到,不同的词对应的bit位置可能相同,当词很多的情况时,可能大部分bit位置都是1,这时查询taobao可能对应的位置都为1,只能说明taobao一词可能存在,不是一定存在的。
使用布隆过滤器
导入依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
代码
public class Test {
private static int size = 1000000;//预计要插入多少数据
private static double fpp = 0.01;//期望的误判率
private static 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 < 2000000; i++) {
if (bloomFilter.mightContain(i)) {
count++;
System.out.println(i + "误判了");
}
}
System.out.println("总共的误判数:" + count);
}
}
应用场景
1.缓存穿透,当大量访问不存在数据的请求到达时,先用布隆过滤器过滤,避免直接去查库,查出来不存在。
public String get(String key) {
String value = redis.get(key);
if (value == null) {
// redis中不存在该缓存
if(!bloomfilter.mightContain(key)){
//布隆过滤器也没有,直接返回
return null;
}else{
//布隆过滤器中能查到,不代表一定有,查出来放入redis,同样也可以避免缓存穿透
value = db.get(key);
redis.set(key, value);
}
}
return value;
}
2.反垃圾邮件、垃圾短信,用布隆过滤器判断这些号码是否存在布隆过滤器中。