海量資料處理——布隆過濾器(Bloom Filter)

來源:互聯網
上載者:User

  Bloom Filter是1970年由Bloom提出的,最初廣泛用於拼字檢查和資料庫系統中。近年來,隨著電腦和互連網技術的發展,資料集的不斷擴張使得Bloom Filter獲得了新生,各種新的應用和變種不斷湧現。Bloom Filter是一個空間效率很高的隨機資料結構,它由一個位元組和一組hash映射函數組成。Bloom Filter可以用於檢索一個元素是否在一個集合中,它的優點是空間效率和查詢時間都遠遠超過一般的演算法,缺點是有一定的誤識別率。因此Bloom Filter不適合那些“零錯誤”的應用場合。而在能容忍低錯誤率的應用場合下,Bloom Filter通過極少的錯誤換取了儲存空間的極大節省。

(1)執行個體比較

  假設要你寫一個網路蜘蛛(web crawler)。由於網路間的連結錯綜複雜,蜘蛛在網路間爬行很可能會形成“環”。為了避免形成“環”,就需要知道蜘蛛已經訪問過那些URL。給一個URL,怎樣知道蜘蛛是否已經訪問過呢?稍微想想,就會有如下幾種方案:

  1. 將訪問過的URL儲存到資料庫。
  2. 用HashSet將訪問過的URL儲存起來。那隻需接近O(1)的代價就可以查到一個URL是否被訪問過了。
  3. URL經過MD5或SHA-1等單向雜湊後再儲存到HashSet或資料庫。
  4. Bit-Map方法。建立一個BitSet,將每個URL經過一個雜湊函數映射到某一位。

 方法1~3都是將訪問過的URL完整儲存,方法4則只標記URL的一個映射位。以上方法在資料量較小的情況下都能完美解決問題,但是當資料量變得非常龐大時問題就來了:

  方法1的缺點:資料量變得非常龐大後關係型資料庫查詢的效率會變得很低。而且每來一個URL就啟動一次資料庫查詢是不是太小題大做了?
  方法2的缺點:太消耗記憶體。隨著URL的增多,佔用的記憶體會越來越多。就算只有1億個URL,每個URL只算50個字元,就需要5GB記憶體。
  方法3:由於字串經過MD5處理後的資訊摘要長度只有128Bit,SHA-1處理後也只有160Bit,因此方法3比方法2節省了好幾倍的記憶體。
  方法4消耗記憶體是相對較少的,但缺點是單一雜湊函數發生衝突的機率太高。還記得資料結構課上學過的Hash表衝突的各種解決方案嗎?若要降低衝突發生的機率到1%,就要將BitSet的長度設定為URL個數的100倍。

  實質上上面的演算法都忽略了一個重要的隱含條件:允許小機率的出錯,不一定要100%準確!也就是說少量url實際上沒有沒網路蜘蛛訪問,而將它們錯判為已訪問的代價是很小的——大不了少抓幾個網頁唄。

(2)Bloom Filter定義

  Bloom Filter是一個有m位的位元組,初始全為0,並有k個各自獨立的雜湊函數。

    (註:Bloom Filter跟單雜湊函數Bit-Map不同之處在於:Bloom Filter使用了k個雜湊函數,每個字串跟k個bit對應。從而降低了衝突的機率)

添加操作:
  每個元素,用k個雜湊Function Compute出大小為k的雜湊向量(h1,h2...hk),將向量裡的每個雜湊值對應的位設定為1。時間複雜度為o(n),一般字串雜湊函數的時間複雜度也就是o(n)。

查詢操作:和添加類似,先計算出雜湊向量,如果每個雜湊值對應的位都為1,則該元素存在。時間複雜度與添加操作相同。

(3)False Position

  如果某元素不在Bloom Filter中,但是它所有雜湊值的位置均被設為1。這種情況就是False Position,也就是誤判。Bloom Filter允許這種情況發生,且不可避免,我們關心的是False Position發生的概念,如何使其降低到最小。

  1)雜湊函數的選擇
  雜湊函數的選擇對效能的影響應該是很大的,一個好的雜湊函數要能近似等機率的將字串映射到各個Bit。選擇k個不同的雜湊函數比較麻煩,一種簡單的方法是選擇一個雜湊函數,然後送入k個不同的參數。

  2)bit數組大小的選擇
  雜湊函數個數k、位元組大小m及字串數量n之間存在相互關係。相關文獻證明了對於給定的m、n,當 k = ln(2)* m/n 時出錯的機率是最小的。  

(4)優缺點

 優點:

    查詢操作十分高效
  節省空間的
  易於擴充成並行
  集合計算方便
  代碼實現方便

缺點:

      有誤判的機率,即存在False Position
  無法擷取集合中的元素資料
  不支援刪除操作(刪除會影響其他字串)

  1. 註:對於不支援刪除操作,現在對其進行了擴充:Counting bloomfilter(CBF),這是一種基本Bloom Filter的變體,CBF將基本Bloom Filter每一個Bit改為一個計數器,這樣就可以實現刪除字串的功能了。

(5)實際應用

1)加速查詢

  適用於一些key-value儲存系統,當values存在硬碟時,查詢就是件費時的事。將Storage的資料都插入Filter,在Filter中查詢都不存在時,那就不需要去Storage查詢了。當False Position出現時,只是會導致一次多餘的Storage查詢。其:

                                     

 如:Google的BigTable也使用了Bloom Filter,以減少不存在的行或列在磁碟上的查詢,大大提高了資料庫的查詢操作的效能。
   Internet Cache Protocol中的Proxy-Cache很多都是使用Bloom Filter儲存URLs,除了高效的查詢外,還能很方便得傳輸交換Cache資訊。

2)網路應用

  P2P網路中尋找資源操作,可以對每條網路通路儲存Bloom Filter,當命中時,則選擇該通路訪問。
  廣播訊息時,可以檢測某個IP是否已發包。
  檢測廣播訊息包的環路,將Bloom Filter儲存在包裡,每個節點將自己添加入Bloom Filter。
  資訊隊列管理,使用Counter Bloom Filter管理資訊流量。

3)垃圾郵件地址過濾

  像網易,QQ這樣的公眾電子郵件(email)供應商,總是需要過濾來自發送垃圾郵件的人(spamer)的垃圾郵件。一個辦法就是記錄下那些發垃圾郵件的email 地址。由於那些寄件者不停地在註冊新的地址,全世界少說也有幾十億個發垃圾郵件的地址,將他們都存起來則需要大量的網路伺服器。如果用雜湊表,每儲存一億個 email 地址,就需要1.6GB 的記憶體(用雜湊表實現的具體辦法是將每一個email 地址對應成一個八位元組的資訊指紋,然後將這些資訊指紋存入雜湊表,由於雜湊表的儲存效率一般只有50%,因此一個email 地址需要佔用十六個位元組。一億個地址大約要1.6GB, 即十六億位元組的記憶體)。因此存貯幾十億個郵件地址可能需要上百GB 的記憶體。而Bloom Filter只需要雜湊表1/8 到1/4 的大小就能解決同樣的問題。Bloom Filter決不會漏掉任何一個在黑名單中的可疑地址。而至於誤判問題,常見的補救辦法是在建立一個小的白名單,儲存那些可能別誤判的郵件地址。

(6)代碼實現

代碼實現請見:http://blog.csdn.net/forestlight/article/details/6839180 ,該文章中給出了一個比較詳細的實現用例,其中有幾個痛點:

1)Bloom Filter的建立函數BLOOM *bloom_create(size_t size, size_t nfuncs, ...);這是一個可變參數函數,裡面涉及了可變參數的內容,如vg_list,vg_start,vg_arg,vg_end這些,可參考上一篇文章“關於C、C++中可變參數的簡介——(va_list,va_start,va_arg,va_end)”。

2) 關於typedef unsigned int (*hashfunc_t)(const char *); 這是一個函數類型的指標,可參考以前寫的“指標函數 vs 函數指標” 。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.