Bloom Filter布隆過濾器
算法背景
如果想判斷一個元素是不是在一個集合里,一般想到的是將集合中所有元素保存起來,然后通過比較確定。鏈表、樹、散列表(又叫哈希
表,Hash table)等等數據結構都是這種思路,存儲位置要么是磁盤,要么是內存。很多時候要么是以時間換空間,要么是以空間換時
間。
在響應時間要求比較嚴格的情況下,如果我們存在內里,那么隨着集合中元素的增加,我們需要的存儲空間越來越大,以及檢索的時間越
來越長,導致內存開銷太大、時間效率變低。
此時需要考慮解決的問題就是,在數據量比較大的情況下,既滿足時間要求,又滿足空間的要求。即我們需要一個時間和空間消耗都比較
小的數據結構和算法。Bloom Filter就是一種解決方案。
Bloom Filter 概念
布隆過濾器(英語:Bloom Filter)是1970年由布隆提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數。布隆過濾器可以
用於檢索一個元素是否在一個集合中。它的優點是空間效率和查詢時間都遠遠超過一般的算法,缺點是有一定的誤識別率和刪除困難。
Bloom Filter(BF)是一種空間效率很高的隨機數據結構,它利用位數組很簡潔地表示一個集合,並能判斷一個元素是否屬於這個集合。
它是一個判斷元素是否存在集合的快速的概率算法。Bloom Filter有可能會出現錯誤判斷,但不會漏掉判斷。也就是Bloom Filter判斷元
素不再集合,那肯定不在。如果判斷元素存在集合中,有一定的概率判斷錯誤。因此,Bloom Filter”不適合那些“零錯誤的應用場合。
而在能容忍低錯誤率的應用場合下,Bloom Filter比其他常見的算法(如hash,折半查找)極大節省了空間。
Bloom Filter 原理
布隆過濾器的原理是,當一個元素被加入集合時,通過K個散列函數將這個元素映射成一個位數組中的K個點,把它們置為1。檢索時,我
們只要看看這些點是不是都是1就(大約)知道集合中有沒有它了:如果這些點有任何一個0,則被檢元素一定不在;如果都是1,則被檢
元素很可能在。這就是布隆過濾器的基本思想。
Bloom Filter跟單哈希函數Bit-Map不同之處在於:Bloom Filter使用了k個哈希函數,每個字符串跟k個bit對應。從而降低了沖突的概
率。
Bloom Filter的缺點
bloom filter之所以能做到在時間和空間上的效率比較高,是因為犧牲了判斷的准確率、刪除的便利性
存在誤判,可能要查到的元素並沒有在容器中,但是hash之后得到的k個位置上值都是1。如果bloom filter中存儲的是黑名單,
那么可以通過建立一個白名單來存儲可能會誤判的元素。
刪除困難。一個放入容器的元素映射到bit數組的k個位置上是1,刪除的時候不能簡單的直接置為0,可能會影響其他元素的判
斷。可以采用Counting Bloom Filter
Bloom Filter 實現
布隆過濾器有許多實現與優化,Guava中就提供了一種Bloom Filter的實現。
在使用bloom filter時,繞不過的兩點是預估數據量n以及期望的誤判率fpp,
在實現bloom filter時,繞不過的兩點就是hash函數的選取以及bit數組的大小。
對於一個確定的場景,我們預估要存的數據量為n,期望的誤判率為fpp,然后需要計算我們需要的Bit數組的大小m,以及hash函數的個
數k,並選擇hash函數
(1)Bit數組大小選擇
根據預估數據量n以及誤判率fpp,bit數組大小的m的計算方式:
(2)哈希函數選擇
由預估數據量n以及bit數組長度m,可以得到一個hash函數的個數k:
哈希函數的選擇對性能的影響應該是很大的,一個好的哈希函數要能近似等概率的將字符串映射到各個Bit。選擇k個不同的哈希函數比較
麻煩,一種簡單的方法是選擇一個哈希函數,然后送入k個不同的參數