布隆過濾器解決緩存穿透的原理

布隆過濾器

作用

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章