Bloom Filter

Bloom Filter(BF)是一種空間效率很高的隨機數據結構,它利用位數組很簡潔地表示一個集合,並能判斷一個元素是否屬於這個集合。它是一個判斷元素是否存在集合的快速的概率算法。

Bloom Filter有可能會出現錯誤判斷,但不會漏掉判斷。也就是Bloom Filter判斷元素不在集合,那肯定不在。如果判斷元素存在集合中,有一定的概率判斷錯誤。因此,Bloom Filter不適合那些“零錯誤”的應用場合。而在能容忍低錯誤率的應用場合下,Bloom Filter比其他常見的算法(如hash,折半查找)極大節省了空間。它的優點是空間效率和查詢時間都遠遠超過一般的算法,缺點是有一定的誤識別率和刪除困難。

 

Bloom-Filter算法的核心思想就是利用多個不同的Hash函數來解決“衝突”。計算某元素x是否在一個集合中,首先能想到的方法就是將所有的已知元素保存起來構成一個集合R,然後用元素x跟這些R中的元素一一比較來判斷是否存在於集合R中;我們可以採用鏈表等數據結構來實現。但是,隨着集合R中元素的增加,其佔用的內存將越來越大。試想,如果有幾千萬個不同網頁需要下載,所需的內存將足以佔用掉整個進程的內存地址空間。即使用MD5,UUID這些方法將URL轉成固定的短小的字符串,內存佔用也是相當巨大的。於是,我們會想到用Hash table的數據結構,運用一個足夠好的Hash函數將一個URL映射到二進制位數組(位圖數組)中的某一位。如果該位已經被置爲1,那麼表示該URL已經存在。Hash存在一個衝突(碰撞)的問題,用同一個Hash得到的兩個URL的值有可能相同。爲了減少衝突,我們可以多引入幾個Hash,如果通過其中的一個Hash值我們得出某元素不在集合中,那麼該元素肯定不在集合中。只有在所有的Hash函數告訴我們該元素在集合中時,才能確定該元素存在於集合中。這便是Bloom-Filter的基本思想。

Bloom Filter參數與公式

m bit數組的寬度(bit數)
n 加入其中的key的數量
k 使用的hash函數的個數
f False Positive的比率

Bloom Filter的f滿足下列公式:

在給定m和n時,能夠使f最小化的k值爲:

此時給出的f爲:

根據以上公式,對於任意給定的f,我們有:

n = m ln(0.6185) / ln(f)  [1]
同時,我們需要k個hash來達成這個目標:
k = - ln(f) / ln(2)        [2]
由於k必須取整數,我們在Bloom Filter的程序實現中,還應該使用上面的公式來求得實際的f:
f = (1 – e-kn/m)k       [3]
以上3個公式是程序實現Bloom Filter的關鍵公式。

Bloom Filter的缺點

       1)Bloom Filter無法從Bloom Filter集合中刪除一個元素。因爲該元素對應的位會牽動到其他的元素。所以一個簡單的改進就是 counting Bloom filter,用一個counter數組代替位數組,就可以支持刪除了。 此外,Bloom Filter的hash函數選擇會影響算法的效果。
       2)還有一個比較重要的問題,如何根據輸入元素個數n,確定位數組m的大小及hash函數個數,即hash函數選擇會影響算法的效果。當hash函數個數k=(ln2)*(m/n)時錯誤率最小。在錯誤率不大於E的情況 下,m至少要等於n*lg(1/E) 才能表示任意n個元素的集合。但m還應該更大些,因爲還要保證bit數組裏至少一半爲0,則m應 該>=nlg(1/E)*lge ,大概就是nlg(1/E)1.44倍(lg表示以2爲底的對數)。
舉個例子我們假設錯誤率爲0.01,則此時m應大概是n的13倍。這樣k大概是8個。

 注意:
         這裏m與n的單位不同,m是bit爲單位,而n則是以元素個數爲單位(準確的說是不同元素的個數)。通常單個元素的長度都是有很多bit的。所以使用bloom filter內存上通常都是節省的。
       一般BF可以與一些key-value的數據庫一起使用,來加快查詢。由於BF所用的空間非常小,所有BF可以常駐內存。這樣子的話,對於大部分不存在的元素,我們只需要訪問內存中的BF就可以判斷出來了,只有一小部分,我們需要訪問在硬盤上的key-value數據庫。從而大大地提高了效率。

應用

Bloom-Filter一般用於在大數據量的集合中判定某元素是否存在。例如郵件服務器中的垃圾郵件過濾器。在搜索引擎領域,Bloom-Filter最常用於網絡蜘蛛(Spider)的URL過濾,網絡蜘蛛通常有一個URL列表,保存着將要下載和已經下載的網頁的URL,網絡蜘蛛下載了一個網頁,從網頁中提取到新的URL後,需要判斷該URL是否已經存在於列表中。此時,Bloom-Filter算法是最好的選擇。

1.key-value 加快查詢
       一般Bloom-Filter可以與一些key-value的數據庫一起使用,來加快查詢。一般key-value存儲系統的values存在硬盤,查詢就是件費時的事。將Storage的數據都插入Filter,在Filter中查詢都不存在時,那就不需要去Storage查詢了。當False Position出現時,只是會導致一次多餘的Storage查詢。
       由於Bloom-Filter所用的空間非常小,所有BF可以常駐內存。這樣子的話,對於大部分不存在的元素,我們只需要訪問內存中的Bloom-Filter就可以判斷出來了,只有一小部分,我們需要訪問在硬盤上的key-value數據庫。從而大大地提高了效率。如圖:
 
2 .Google的BigTable
        Google的BigTable也使用了Bloom Filter,以減少不存在的行或列在磁盤上的查詢,大大提高了數據庫的查詢操作的性能。


3. Proxy-Cache
      在Internet Cache Protocol中的Proxy-Cache很多都是使用Bloom Filter存儲URLs,除了高效的查詢外,還能很方便得傳輸交換Cache信息。


4.網絡應用
      1)P2P網絡中查找資源操作,可以對每條網絡通路保存Bloom Filter,當命中時,則選擇該通路訪問。
      2)廣播消息時,可以檢測某個IP是否已發包。
      3)檢測廣播消息包的環路,將Bloom Filter保存在包裏,每個節點將自己添加入Bloom Filter。
     4)信息隊列管理,使用Counter Bloom Filter管理信息流量。
 
5. 垃圾郵件地址過濾
   像網易,QQ這樣的公衆電子郵件(email)提供商,總是需要過濾來自發送垃圾郵件的人(spamer)的垃圾郵件。一個辦法就是記錄下那些發垃圾郵件的 email地址。由於那些發送者不停地在註冊新的地址,全世界少說也有幾十億個發垃圾郵件的地址,將他們都存起來則需要大量的網絡服務器。如果用哈希表,每存儲一億個 email地址,就需要 1.6GB的內存(用哈希表實現的具體辦法是將每一個email地址對應成一個八字節的信息指紋,然後將這些信息指紋存入哈希表,由於哈希表的存儲效率一般只有 50%,因此一個 email地址需要佔用十六個字節。一億個地址大約要1.6GB,即十六億字節的內存)。因此存貯幾十億個郵件地址可能需要上百 GB的內存。而Bloom Filter只需要哈希表 1/8到1/4 的大小就能解決同樣的問題。BloomFilter決不會漏掉任何一個在黑名單中的可疑地址。而至於誤判問題,常見的補救辦法是在建立一個小的白名單,存儲那些可能別誤判的郵件地址。

參考:http://blog.csdn.net/hguisu/article/details/7866173

發佈了77 篇原創文章 · 獲贊 13 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章