布隆過濾器基礎原理


布隆過濾器(Bloom Filter)

是1970年由布隆提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數。布隆過濾器可以用於檢索一個元素是否在一個集合中。

它的優點是空間效率和查詢時間都比一般的算法要好的多,缺點是有一定的誤識別率和刪除困難。

本質上布隆過濾器是一種數據結構,比較巧妙的概率型數據結構(probabilistic data structure),特點是高效地插入和查詢,可以用來告訴你

“某樣東西一定不存在或者可能存在”,可能存在的前提下再去數據庫進行准確查找,或者查找白名單。

 

實現原理

HashMap 的問題

講述布隆過濾器的原理之前,我們先思考一下,通常你判斷某個元素是否存在用的是什么?應該蠻多人回答 HashMap 吧,確實可以將值映射到 HashMap 的 Key,然后可以在 O(1) 的時間復雜度內返回結果,效率奇高。

但是 HashMap 的實現也有缺點,例如存儲容量占比高,考慮到負載因子的存在,通常空間是不能被用滿的,而一旦你的值很多例如上億的時候,那 HashMap 占據的內存大小就變得很可觀了。

還比如說你的數據集存儲在遠程服務器上,本地服務接受輸入,而數據集非常大不可能一次性讀進內存構建 HashMap 的時候,也會存在問題。

 

位數組

為了節省內存:用數組來存儲數字,數字的商為數組下標,數字的余數為,

例如,存儲32位的數,36這個數字,36/32商為1余數為4,數組array[0]存儲一個32位的數(即a[0]就能表示32個數字,即4個字節就能表示32個32位的數,是不是很省內存),1<<4 二進制為10000,轉為十進制就是16,所以array[0]=16;

假如下一個數還是array[0],那就邏輯或一下就能把對應的1加上去了!

//判斷當前系統是32位還是64位(^uint(0)在32位系統上返回的是0XFFFFFFFF,在64位系統上返回的是0xFFFFFFFFFFFFFFFF)
const target int = 32 << (^uint(0) >> 63)

func (s *IntSet) Add(numbers ...int) {
    for _, numebr := range numbers {
        x := numebr
        a, b := x/target, uint(x%target)
        array[a] |= 1 << b
    }
}

 

布隆過濾器數據結構

布隆過濾器是一個 bit 向量或者說 bit 數組,長這樣:

 

 
image

如果我們要映射一個值到布隆過濾器中,我們需要使用多個不同的哈希函數生成多個哈希值,並對每個生成的哈希值指向的 bit 位置 1,例如針對值 “baidu” 和三個不同的哈希函數分別生成了哈希值 1、4、7,則上圖轉變為:

 

 
image

Ok,我們現在再存一個值 “tencent”,如果哈希函數返回 3、4、8 的話,圖繼續變為:

 

 
image

值得注意的是,4 這個 bit 位由於兩個值的哈希函數都返回了這個 bit 位,因此它被覆蓋了。現在我們如果想查詢 “dianping” 這個值是否存在,哈希函數返回了 1、5、8三個值,

結果我們發現 5 這個 bit 位上的值為 0,說明沒有任何一個值映射到這個 bit 位上,因此我們可以很確定地說 “dianping” 這個值不存在。而當我們需要查詢 “baidu” 這個值是否存在的話,

那么哈希函數必然會返回 1、4、7,然后我們檢查發現這三個 bit 位上的值均為 1,那么我們可以說 “baidu” 存在了么?答案是不可以,只能是 “baidu” 這個值可能存在。

這是為什么呢?答案跟簡單,因為隨着增加的值越來越多,被置為 1 的 bit 位也會越來越多,這樣某個值 “taobao” 即使沒有被存儲過,但是萬一哈希函數返回的三個 bit 位都被其他值置位了 1 ,那么程序還是會判斷 “taobao” 這個值存在。

 

應用:

1.網頁URL的去重

2.垃圾郵件的判別

3.集合重復元素的判別

4.查詢加速(比如基於key-value的存儲系統)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM