海量數據處理之Bloom Filter詳解

前言

    本博客內曾已經整理過十道海量數據處理面試題與十個方法大總結。接下來,本博客內會重點分析那些海量數據處理的方法,並重寫十道海量數據處理的面試題。如果有任何問題,歡迎不吝指正。謝謝。

一、什麼是Bloom Filter

    Bloom Filter是一種空間效率很高的隨機數據結構,它的原理是,當一個元素被加入集合時,通過K個Hash函數將這個元素映射成一個位陣列(Bit array)中的K個點,把它們置爲1。檢索時,我們只要看看這些點是不是都是1就(大約)知道集合中有沒有它了:如果這些點有任何一個0,則被檢索元素一定不在;如果都是1,則被檢索元素很可能在。這就是布隆過濾器的基本思想。

    但Bloom Filter的這種高效是有一定代價的:在判斷一個元素是否屬於某個集合時,有可能會把不屬於這個集合的元素誤認爲屬於這個集合(false positive)。因此,Bloom Filter不適合那些“零錯誤”的應用場合。而在能容忍低錯誤率的應用場合下,Bloom Filter通過極少的錯誤換取了存儲空間的極大節省。

    有人可能想知道它的中文叫法,倒是有被譯作稱布隆過濾器。該不該譯,譯的是否恰當,由諸君品之。下文之中,如果有諸多公式不慎理解,也無礙,只作稍稍瞭解即可。

1.1、集合表示和元素查詢

    下面我們具體來看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,且有兩個哈希函數選中同一個位置(從左邊數第五位,即第二個“1“處)。

    在判斷y是否屬於這個集合時,我們對y應用k次哈希函數,如果所有hi(y)的位置都是1(1≤i≤k),那麼我們就認爲y是集合中的元素,否則就認爲y不是集合中的元素。下圖中y1就不是集合中的元素(因爲y1有一處指向了“0”位)。y2或者屬於這個集合,或者剛好是一個false positive。

1.2、錯誤率估計

    前面我們已經提到了,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通常在分析中更爲方便。

1.3、最優的哈希函數個數

    既然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’取得最小值。

1.4、位數組的大小

    下面我們來看看,在不超過一定錯誤率的情況下,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/?)大了log2e≈ 1.44倍。這說明在哈希函數的個數取到最優時,要讓錯誤率不超過?,m至少需要取到最小值的1.44倍。

1.5、概括

    在計算機科學中,我們常常會碰到時間換空間或者空間換時間的情況,即爲了達到某一個方面的最優而犧牲另一個方面。Bloom Filter在時間空間這兩個因素之外又引入了另一個因素:錯誤率。在使用Bloom Filter判斷一個元素是否屬於某個集合時,會有一定的錯誤率。也就是說,有可能把不屬於這個集合的元素誤認爲屬於這個集合(False Positive),但不會把屬於這個集合的元素誤認爲不屬於這個集合(False Negative)。在增加了錯誤率這個因素之後,Bloom Filter通過允許少量的錯誤來節省大量的存儲空間。

    自從Burton Bloom在70年代提出Bloom Filter之後,Bloom Filter就被廣泛用於拼寫檢查和數據庫系統中。近一二十年,伴隨着網絡的普及和發展,Bloom Filter在網絡領域獲得了新生,各種Bloom Filter變種和新的應用不斷出現。可以預見,隨着網絡應用的不斷深入,新的變種和應用將會繼續出現,Bloom Filter必將獲得更大的發展。

二、適用範圍

    可以用來實現數據字典,進行數據的判重,或者集合求交集

三、基本原理及要點

    對於原理來說很簡單,位數組+k個獨立hash函數。將hash函數對應的值的位數組置1,查找時如果發現所有hash函數對應位都是1說明存在,很明顯這 個過程並不保證查找的結果是100%正確的。同時也不支持刪除一個已經插入的關鍵字,因爲該關鍵字對應的位會牽動到其他的關鍵字。所以一個簡單的改進就是 counting Bloom filter,用一個counter數組代替位數組,就可以支持刪除了。

    還有一個比較重要的問題,如 何根據輸入元素個數n,確定位數組m的大小及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內存上通常都是節省的。

四、擴展

    Bloom filter將集合中的元素映射到位數組中,用k(k爲哈希函數個數)個映射位是否全1表示元素在不在這個集合中。Counting bloom filter(CBF)將位數組中的每一位擴展爲一個counter,從而支持了元素的刪除操作。Spectral Bloom Filter(SBF)將其與集合元素的出現次數關聯。SBF採用counter中的最小值來近似表示元素的出現頻率。

五、問題實例

    給你A,B兩個文件,各存放50億條URL,每條URL佔用64字節,內存限制是4G,讓你找出A,B文件共同的URL。如果是三個乃至n個文件呢?

根據這個問題我們來計算下內存的佔用,4G=2^32大概是40億*8大概是340億,n=50億,如果按出錯率0.01算需要的大概是650億個bit。 現在可用的是340億,相差並不多,這樣可能會使出錯率上升些。另外如果這些urlip是一一對應的,就可以轉換成ip,則大大簡單了。

參考文獻及推薦閱讀
  1. http://blog.csdn.net/jiaomeng/article/details/1495500
  2. http://blog.redfox66.com/post/2010/09/24/mass-data-topic-1-start.aspx
  3. 維基百科上關於布隆過濾器的介紹:http://zh.wikipedia.org/zh-cn/%E5%B8%83%E9%9A%86%E8%BF%87%E6%BB%A4%E5%99%A8
  4. 海量數據處理利器之Bloom Filter:http://www.dbafree.net/?p=36
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章