看到hadoop join和hbase都有bloom filter的實作,找了找他的介紹文檔
轉http://blog.csdn.net/wbia2010lkl/article/details/5953629
轉http://blog.csdn.net/jiaomeng/article/details/1495500
在javaEyes上找到一篇挺有用的文章,希望能對大家了解Bloom filter有幫助
1 Overview
Bloom filter最早由 Burton Howard Bloom提出,是一種用于判斷成員是否存在于某個集合中的資料結構。 Bloom filter的判斷基于機率論:
-
- 如果某個成員存在于集合中,那麼Bloom filter不會傳回假(即不存在),也就是說false negative是不可能的。
- 如果某個成員實際上不存在于集合中,Bloom filter可能傳回真(即存在),這種情況被稱為false positive。
- (hbase的hfile使用bloom fitler,可以确定的告訴你指定的rk不在目前hfile中,但是不确定他是否在目前hfile中)
Bloom filter通常被實作為一個包含 m 位的位數組(bit array),所有位的初始值都為0。Bloom filter支援以下兩種類型的操作:
- add。将成員添加到Bloom filter中。以該成員為參數調用 k 個索引函數(index functions),得到 k 個位數組的索引值,取值範圍是 [0, m), 然後将位數組的對應位設定為1。
- query。判斷某個成員是否已經添加到Bloom filter中。以該成員為參數調用 k 個索引函數,得到 k 個位數組的索引值,然後根據這些索引值檢查位數組:當位數組中所有的對應位均為1時,那麼認為該成員已經存在。
如果query的結果為真(即positive),那麼實際上存在以下兩種可能性:
- 該成員已經被add到集合中,即該成員的确存在。
- 該成員未被add到集合中,但是query過程中檢查的所有位均被設定為1(由于添加的其它成員導緻)。這種情況被稱為false positive。
傳統的Bloom filter 不支援從集合中删除成員。對于每個添加到Bloom filter中的成員,實際上将其位數組中的 k 位設定為1。盡管将這些位重置為0可以保證從Bloom filter中删除該成員,但是這樣做的副作用是可能會影響某些其它成員,因為其它成員也可能被映射到這些被重置為0的位中的一位或者多位, 進而最終導緻false negatives。對于Bloom filter而言,false negatives是不被允許的。 Counting Bloom filter由于采用了計數,是以支援remove操作。
Bloom filter 使用的 k 個index functions,有時也被稱為hash functions,它們通常被假定為彼此獨立,傳回值在可能的取值範圍内均勻分布(這是以下一系列數學證明的基礎)。
2 The Math
Bloom filter的基本概念并不複雜,接下來分析一下query操作對某個未被添加的成員傳回positive(即false positive)的機率:
假設p是位數組中某一位為1的機率, 那麼false positive的機率是 pk 。如果n是已經添加到Bloom filter中的成員個數,那麼 p = 1 – (1 – 1/m)nk,經過一系列推導得到 p ≈ ( 1 – e-kn/m ) k , 當 k = m / n * ln2 時(ln 即 loge ),p為最小值。 例如當k = 8, m/n = 10時, false positive的理論值為0.00846。以下是段計算false positive的執行個體代碼:
Java代碼
- public static double calculateFalsePositiveProbability(int k, int m, int n) {
- return Math.pow((1 - Math.exp(-k * (double) n / (double) m)), k);
- }
對于某些應用而言,false positive的機率已經是一個足夠好的判斷Bloom filter準确性的名額,Peter C.Dillinger 和 Panagiotis Manolios 在其Bloom Filters in Probablistic Verfification的論文中指出,對于query過程中的不确定性, state omission 是一個更合适的名額。建議感興趣的讀者閱讀該論文,順便也可以複習一下相關的數學知識。
3 Refinement
So far, so good。 跟普通的HashMap相比, Bloom filter不需要在記憶體中儲存key和value, 而是位數組中的若幹個位即可,這在記憶體使用上是個巨大的節省,當然前提是能容忍一定機率的false positives。但是傳統的Bloom filter存在以下兩個嚴重的缺陷:
- 為了保證足夠低的false positive機率,通常索引函數的個數 k 比較大(例如十幾甚至幾十,但通常不超過32)。 能找到這麼多個random,uniform and independent的索引函數并不是一件容易的事情。
- 數量衆多的索引函數,導緻add和query的性能不高。
Peter C.Dillinger 和 Panagiotis Manolios在其論文中指出,fingerprinting Bloom filter可以有效地減少索引函數的個數,并且對準确性的影響可以小到忽略。這對于傳統的Bloom filter來說,是個重大的改進。筆者使用了其中介紹的triple hashing,認為效果比較明顯。
4 Implementation
如果Google以Java實作的Bloom filter, java-bloomfilter 可能是最容易找到的實作之一。它采用的是傳統的Bloom filter算法:使用的 k 個索引函數(預設都是MD5),隻是索引函數在進行計算時對參數的加鹽(salting)不同而已。筆者認為 java-bloomfilter 的性能可能有待提升。
Hadoop common的util包中也提供了一個Bloom Filter的實作,此外其hash包還提供了JenkinsHash 和 MurmurHash 兩個Hash算法。筆者感覺Hadoop 的Bloom filter的實作方式類似fingerprinting Bloom filter,但是沒有使用double hashing 或者tripple hashing。
此外關于位數組的實作方式,可能最直接想法的是使用java.util.BitSet。不過筆者認為如果處理的資料量很大、或者性能要求比較高,那麼不建議使用java.util.BitSet, 因為java.util.BitSet的記憶體使用方式、總體性能都不是很理想。
5 Reference
- Bloom Filters in Probablistic Verfification. Peter C.Dillinger and Panagiotis Manolios
- Hadoop的Bloom filter實作。http://hadoop.apache.org/common/
- java-bloomfilter. http://code.google.com/p/java-bloomfilter/
-------------------------------------------------------------------------------
Bloom Filter概念和原理
焦萌 2007年1月27日
Bloom Filter是一種空間效率很高的随機資料結構,它利用位數組很簡潔地表示一個集合,并能判斷一個元素是否屬于這個集合。Bloom Filter的這種高效是有一定代價的:在判斷一個元素是否屬于某個集合時,有可能會把不屬于這個集合的元素誤認為屬于這個集合(false positive)。是以,Bloom Filter不适合那些“零錯誤”的應用場合。而在能容忍低錯誤率的應用場合下,Bloom Filter通過極少的錯誤換取了存儲空間的極大節省。
集合表示和元素查詢
下面我們具體來看Bloom Filter是如何用位數組表示集合的。初始狀态時,Bloom Filter是一個包含m位的位數組,每一位都置為0。
為了表達S={x1, x2,…,xn}這樣一個n個元素的集合,Bloom Filter使用k個互相獨立的哈希函數(Hash Function),它們分别将集合中的每個元素映射到{1,…,m}的範圍中。對任意一個元素x,第i個哈希函數映射的位置hi(x)就會被置為1(1≤i≤k)。注意,如果一個位置多次被置為1,那麼隻有第一次會起作用,後面幾次将沒有任何效果。在下圖中,k=3,且有兩個哈希函數選中同一個位置(從左邊數第五位)。
在判斷y是否屬于這個集合時,我們對y應用k次哈希函數,如果所有hi(y)的位置都是1(1≤i≤k),那麼我們就認為y是集合中的元素,否則就認為y不是集合中的元素。下圖中y1就不是集合中的元素。y2或者屬于這個集合,或者剛好是一個false positive。
錯誤率估計
前面我們已經提到了,Bloom Filter在判斷一個元素是否屬于它表示的集合時會有一定的錯誤率(false positive rate),下面我們就來估計錯誤率的大小。在估計之前為了簡化模型,我們假設kn<m且各個哈希函數是完全随機的。當集合S={x1, x2,…,xn}的所有元素都被k個哈希函數映射到m位的位數組中時,這個位數組中某一位還是0的機率是:
其中1/m表示任意一個哈希函數選中這一位的機率(前提是哈希函數是完全随機的),(1-1/m)表示哈希一次沒有選中這一位的機率。要把S完全映射到位數組中,需要做kn次哈希。某一位還是0意味着kn次哈希都沒有選中它,是以這個機率就是(1-1/m)的kn次方。令p = e-kn/m是為了簡化運算,這裡用到了計算e時常用的近似:
令ρ為位數組中0的比例,則ρ的數學期望E(ρ)= p’。在ρ已知的情況下,要求的錯誤率(false positive rate)為:
(1-ρ)為位數組中1的比例,(1-ρ)k就表示k次哈希都剛好選中1的區域,即false positive rate。上式中第二步近似在前面已經提到了,現在來看第一步近似。p’隻是ρ的數學期望,在實際中ρ的值有可能偏離它的數學期望值。M. Mitzenmacher已經證明[2] ,位數組中0的比例非常集中地分布在它的數學期望值的附近。是以,第一步的近似得以成立。分别将p和p’代入上式中,得:
相比p’和f’,使用p和f通常在分析中更為友善。
最優的哈希函數個數
既然Bloom Filter要靠多個哈希函數将集合映射到位數組中,那麼應該選擇幾個哈希函數才能使元素查詢時的錯誤率降到最低呢?這裡有兩個互斥的理由:如果哈希函數的個數多,那麼在對一個不屬于集合的元素進行查詢時得到0的機率就大;但另一方面,如果哈希函數的個數少,那麼位數組中的0就多。為了得到最優的哈希函數個數,我們需要根據上一小節中的錯誤率公式進行計算。
先用p和f進行計算。注意到f = exp(k ln(1 − e−kn/m)),我們令g = k ln(1 − e−kn/m),隻要讓g取到最小,f自然也取到最小。由于p = e-kn/m,我們可以将g寫成
根據對稱性法則可以很容易看出當p = 1/2,也就是k = ln2· (m/n)時,g取得最小值。在這種情況下,最小錯誤率f等于(1/2)k ≈ (0.6185)m/n。另外,注意到p是位數組中某一位仍是0的機率,是以p = 1/2對應着位數組中0和1各一半。換句話說,要想保持錯誤率低,最好讓位數組有一半還空着。
需要強調的一點是,p = 1/2時錯誤率最小這個結果并不依賴于近似值p和f。同樣對于f’ = exp(k ln(1 − (1 − 1/m)kn)),g’ = k ln(1 − (1 − 1/m)kn),p’ = (1 − 1/m)kn,我們可以将g’寫成
同樣根據對稱性法則可以得到當p’ = 1/2時,g’取得最小值。
位數組的大小
下面我們來看看,在不超過一定錯誤率的情況下,Bloom Filter至少需要多少位才能表示全集中任意n個元素的集合。假設全集中共有u個元素,允許的最大錯誤率為є,下面我們來求位數組的位數m。
假設X為全集中任取n個元素的集合,F(X)是表示X的位數組。那麼對于集合X中任意一個元素x,在s = F(X)中查詢x都能得到肯定的結果,即s能夠接受x。顯然,由于Bloom Filter引入了錯誤,s能夠接受的不僅僅是X中的元素,它還能夠є (u - n)個false positive。是以,對于一個确定的位數組來說,它能夠接受總共n + є (u - n)個元素。在n + є (u - n)個元素中,s真正表示的隻有其中n個,是以一個确定的位數組可以表示
個集合。m位的位數組共有2m個不同的組合,進而可以推出,m位的位數組可以表示
個集合。全集中n個元素的集合總共有
個,是以要讓m位的位數組能夠表示所有n個元素的集合,必須有
即:
上式中的近似前提是n和єu相比很小,這也是實際情況中常常發生的。根據上式,我們得出結論:在錯誤率不大于є的情況下,m至少要等于n log2(1/є)才能表示任意n個元素的集合。
上一小節中我們曾算出當k = ln2· (m/n)時錯誤率f最小,這時f = (1/2)k = (1/2)mln2 / n。現在令f≤є,可以推出
這個結果比前面我們算得的下界n log2(1/є)大了log2 e ≈ 1.44倍。這說明在哈希函數的個數取到最優時,要讓錯誤率不超過є,m至少需要取到最小值的1.44倍。
總結
在計算機科學中,我們常常會碰到時間換空間或者空間換時間的情況,即為了達到某一個方面的最優而犧牲另一個方面。Bloom Filter在時間空間這兩個因素之外又引入了另一個因素:錯誤率。在使用Bloom Filter判斷一個元素是否屬于某個集合時,會有一定的錯誤率。也就是說,有可能把不屬于這個集合的元素誤認為屬于這個集合(False Positive),但不會把屬于這個集合的元素誤認為不屬于這個集合(False Negative)。在增加了錯誤率這個因素之後,Bloom Filter通過允許少量的錯誤來節省大量的存儲空間。
自從Burton Bloom在70年代提出Bloom Filter之後,Bloom Filter就被廣泛用于拼寫檢查和資料庫系統中。近一二十年,伴随着網絡的普及和發展,Bloom Filter在網絡領域獲得了新生,各種Bloom Filter變種和新的應用不斷出現。可以預見,随着網絡應用的不斷深入,新的變種和應用将會繼續出現,Bloom Filter必将獲得更大的發展。
參考資料
[1] A. Broder and M. Mitzenmacher. Network applications of bloom filters: A survey. Internet Mathematics, 1(4):485–509, 2005.
[2] M. Mitzenmacher. Compressed Bloom Filters. IEEE/ACM Transactions on Networking 10:5 (2002), 604—612.
[3] www.cs.jhu.edu/~fabian/courses/CS600.624/slides/bloomslides.pdf
[4] http://166.111.248.20/seminar/2006_11_23/hash_2_yaxuan.ppt