布隆過濾器
作用
告訴你某個元素一定不存在或者可能存在,相比於傳統的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.反垃圾郵件、垃圾短信,用布隆過濾器判斷這些號碼是否存在布隆過濾器中。