天天看點

數學之美系列二十一 - 布隆過濾器(Bloom Filter)

數學之美系列二十一 - 布隆過濾器(Bloom Filter)

2007年7月3日 上午 09:35:00

<script language=javascript> uT("time4444440318463911176"); </script>

發表者:Google(谷歌)研究員 吳軍

在日常生活中,包括在設計計算機軟體時,我們經常要判斷一個元素是否在一個集合中。比如在字處理軟體中,需要檢查一個英語單詞是否拼寫正确(也就是要判斷它是否在已知的字典中);在 FBI,一個嫌疑人的名字是否已經在嫌疑名單上;在網絡爬蟲裡,一個網址是否被通路過等等。最直接的方法就是将集合中全部的元素存在計算機中,遇到一個新元素時,将它和集合中的元素直接比較即可。一般來講,計算機中的集合是用哈希表(hash table)來存儲的。它的好處是快速準确,缺點是費存儲空間。當集合比較小時,這個問題不顯著,但是當集合巨大時,哈希表存儲效率低的問題就顯現出來了。比如說,一個象 Yahoo,Hotmail 和 Gmai 那樣的公衆電子郵件(email)提供商,總是需要過濾來自發送垃圾郵件的人(spamer)的垃圾郵件。一個辦法就是記錄下那些發垃圾郵件的 email 位址。由于那些發送者不停地在注冊新的位址,全世界少說也有幾十億個發垃圾郵件的位址,将他們都存起來則需要大量的網絡伺服器。如果用哈希表,每存儲一億個 email 位址, 就需要 1.6GB 的記憶體(用哈希表實作的具體辦法是将每一個 email 位址對應成一個八位元組的資訊指紋 googlechinablog.com/2006/08/blog-post.html,然後将這些資訊指紋存入哈希表,由于哈希表的存儲效率一般隻有 50%,是以一個 email 位址需要占用十六個位元組。一億個位址大約要 1.6GB, 即十六億位元組的記憶體)。是以存貯幾十億個郵件位址可能需要上百 GB 的記憶體。除非是超級計算機,一般伺服器是無法存儲的。

今天,我們介紹一種稱作布隆過濾器的數學工具,它隻需要哈希表 1/8 到 1/4 的大小就能解決同樣的問題。

布隆過濾器是由巴頓.布隆于一九七零年提出的。它實際上是一個很長的二進制向量和一系列随機映射函數。我們通過上面的例子來說明起工作原理。

假定我們存儲一億個電子郵件位址,我們先建立一個十六億二進制(比特),即兩億位元組的向量,然後将這十六億個二進制全部設定為零。對于每一個電子郵件位址 X,我們用八個不同的随機數産生器(F1,F2, ...,F8) 産生八個資訊指紋(f1, f2, ..., f8)。再用一個随機數産生器 G 把這八個資訊指紋映射到 1 到十六億中的八個自然數 g1, g2, ...,g8。現在我們把這八個位置的二進制全部設定為一。當我們對這一億個 email 位址都進行這樣的處理後。一個針對這些 email 位址的布隆過濾器就建成了。(見下圖)

數學之美系列二十一 - 布隆過濾器(Bloom Filter)

現在,讓我們看看如何用布隆過濾器來檢測一個可疑的電子郵件位址 Y 是否在黑名單中。我們用相同的八個随機數産生器(F1, F2, ..., F8)對這個位址産生八個資訊指紋 s1,s2,...,s8,然後将這八個指紋對應到布隆過濾器的八個二進制位,分别是 t1,t2,...,t8。如果 Y 在黑名單中,顯然,t1,t2,..,t8 對應的八個二進制一定是一。這樣在遇到任何在黑名單中的電子郵件位址,我們都能準确地發現。

布隆過濾器決不會漏掉任何一個在黑名單中的可疑位址。但是,它有一條不足之處。也就是它有極小的可能将一個不在黑名單中的電子郵件位址判定為在黑名單中,因為有可能某個好的郵件位址正巧對應個八個都被設定成一的二進制位。好在這種可能性很小。我們把它稱為誤識機率。在上面的例子中,誤識機率在萬分之一以下。

布隆過濾器的好處在于快速,省空間。但是有一定的誤識别率。常見的補救辦法是在建立一個小的白名單,存儲那些可能别誤判的郵件位址。

原文:http://googlechinablog.com/2007/07/bloom-filter.html