布隆過濾器(Bloom Filter)初探

布隆過濾器介紹

布隆過濾器(Bloom Filter,下文簡稱BF)由Burton Howard Bloom在1970年提出,是一種空間效率高的概率型數據結構。它專門用來檢測集合中是否存在特定的元素。聽起來是很稀鬆平常的需求,爲什麼要使用BF這種數據結構呢?

產生的契機

回想一下,我們平常在檢測集合中是否存在某元素時,都會採用比較的方法。考慮以下情況:

  • 如果集合用線性表存儲,查找的時間複雜度爲O(n)。
  • 如果用平衡BST(如AVL樹、紅黑樹)存儲,時間複雜度爲O(logn)。
  • 如果用哈希表存儲,並用鏈地址法與平衡BST解決哈希衝突(參考JDK8的HashMap實現方法),時間複雜度也要有O[log(n/m)],m爲哈希分桶數。

     

總而言之,當集合中元素的數量極多時,不僅查找會變得很慢,而且佔用的空間也會大到無法想象。BF就是解決這個矛盾的利器。

設計思想

BF是由一個長度爲m比特的位數組(bit array)k個哈希函數(hash function)組成的數據結構。位數組均初始化爲0,所有哈希函數都可以分別把輸入數據儘量均勻地散列。

當要插入一個元素時,將其數據分別輸入k個哈希函數,產生k個哈希值。以哈希值作爲位數組中的下標,將所有k個對應的比特置爲1。

當要查詢(即判斷是否存在)一個元素時,同樣將其數據輸入哈希函數,然後檢查對應的k個比特。如果有任意一個比特爲0,表明該元素一定不在集合中。如果所有比特均爲1,表明該集合有(較大的)可能性在集合中。爲什麼不是一定在集合中呢?因爲一個比特被置爲1有可能會受到其他元素的影響,這就是所謂“假陽性”(false positive)。相對地,“假陰性”(false negative)在BF中是絕不會出現的。

下圖示出一個m=18, k=3的BF示例。集合中的x、y、z三個元素通過3個不同的哈希函數散列到位數組中。當查詢元素w時,因爲有一個比特爲0,因此w不在該集合中。

 

優缺點與用途

BF的優點是顯而易見的:

  • 不需要存儲數據本身,只用比特表示,因此空間佔用相對於傳統方式有巨大的優勢,並且能夠保密數據;
  • 時間效率也較高,插入和查詢的時間複雜度均爲O(k);
  • 哈希函數之間相互獨立,可以在硬件指令層面並行計算。

但是,它的缺點也同樣明顯:

  • 存在假陽性的概率,不適用於任何要求100%準確率的情境;
  • 只能插入和查詢元素,不能刪除元素,這與產生假陽性的原因是相同的。我們可以簡單地想到通過計數(即將一個比特擴展爲計數值)來記錄元素數,但仍然無法保證刪除的元素一定在集合中。

所以,BF在對查準度要求沒有那麼苛刻,而對時間、空間效率要求較高的場合非常合適,本文第一句話提到的用途即屬於此類。另外,由於它不存在假陰性問題,所以用作“不存在”邏輯的處理時有奇效,比如可以用來作爲緩存系統(如Redis)的緩衝,防止緩存穿透。

 

假陽性率的計算 *

假陽性是BF最大的痛點,因此有必要權衡,比如計算一下假陽性的概率。爲了簡單一點,就假設我們的哈希函數選擇位數組中的比特時,都是等概率的。當然在設計哈希函數時,也應該儘量滿足均勻分佈。

在位數組長度m的BF中插入一個元素,它的其中一個哈希函數會將某個特定的比特置爲1。因此,在插入元素後,該比特仍然爲0的概率是:

現有k個哈希函數,並插入n個元素,自然就可以得到該比特仍然爲0的概率是:

反過來講,它已經被置爲1的概率就是:

也就是說,如果在插入n個元素後,我們用一個不在集合中的元素來檢測,那麼被誤報爲存在於集合中的概率(也就是所有哈希函數對應的比特都爲1的概率)爲:

當n比較大時,根據重要極限公式,可以近似得出假陽性率:

所以,在哈希函數的個數k一定的情況下:

  • 位數組長度m越大,假陽性率越低;
  • 已插入元素的個數n越大,假陽性率越高。

 



轉載鏈接:https://www.jianshu.com/p/bef2ec1c361f

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