布隆過濾器(bloom filter)的原理及在推薦去重中的應用

遇到的問題

在業務中,我須要給每一個用戶保存1w條瀏覽記錄,以後每一次的返回值都要和歷史記錄作一個去重,即保證用戶不會重複看到同一篇文章.redis

這個需求有兩個比較麻煩的地方:算法

1.空間問題

每一個用戶1w條,10w用戶就是10億條數據,應該保存在哪裏呢?sql

Redis?哪裏有那麼大內存給你用.數據庫

Hbase?Hbase我不太瞭解具體原理,聽說每次全量查詢有點慢啊(後來聽大佬說這點數據無壓力的).數組

Mysql?卻是能存下這麼多,可是太影響性能了.緩存

2.時間問題

這個需求對即時性要求仍是比較高的,用戶兩次刷新的間隔可能只有幾秒鐘,在此期間就要完成歷史數據的添加以及過濾.安全

每次返回用戶10條數據,每一條都須要和數據庫中的1w條作比對,聽起來效率就不好的樣子.網絡

在大佬的推薦下,我去了解了一下布隆過濾器,最後初步使用布隆過濾器+Redis+Hbase完成了一個版本,效率和空間佔用都還能夠.函數

布隆過濾器

介紹

如下摘自維基百科:性能

布隆過濾器(英語:Bloom Filter)是1970年由布隆提出的。它其實是一個很長的二進制向量和一系列隨機映射函數。布隆過濾器能夠用於檢索一個元素是否在一個集合中。它的優勢是空間效率和查詢時間都遠遠超過通常的算法,缺點是有必定的誤識別率和刪除困難。

說直白一點就是:布隆過濾器用本身的算法,實現了快速的檢索一個元素是否在一個較大的元素列表之中.

原理

當一個元素被加入集合時,經過K個散列函數將這個元素映射成一個位數組中的K個點,把它們置爲1。檢索時,咱們只要看看這些點是否是都是1就(大約)知道集合中有沒有它了:若是這些點有任何一個0,則被檢元素必定不在;若是都是1,則被檢元素極可能在。這就是布隆過濾器的基本思想。

假設咱們如今得到了一個size=10000的布隆過濾器,分配給咱們的實際上是10000個二進制位,假設k=8,那麼當新添加huyanshi這個元素時,經過8個不一樣的hash函數,能夠拿到8個index值,假設爲1,2300,222,11...,咱們就將這8個index爲下標的位置,置爲1.

當咱們想要檢索huyanshi是否存在時,再次用8個hash函數得到8個index,若是這8個index的位置都爲1,那麼這個元素就很可能存在.若是其中有一位爲0,則該元素必定不存在.

注意上面的可能加粗了,下面就要說優缺點了.

優勢

  1. 效率高,插入和查詢操做都是O(k).
  2. 空間節省,每個元素映射爲一個二進制位,必須節省.
  3. 安全,保存了數據的全集,可是沒有保存數據自己.

缺點

  1. 誤算率,使用了Hash算法,那麼久必然會存在極限巧合下的hash碰撞.會將不存在的數據認爲是存在的.可是存在的數據必定是能夠正確判斷的.
  2. 很難刪除數據.

使用場景

根據優缺點,咱們能夠分析出他的使用場景,那麼就是的正確率要求不是100%,同時存在海量的數據集.

  • 字處理軟件中,須要檢查一個英語單詞是否拼寫正確
  • 在 FBI,一個嫌疑人的名字是否已經在嫌疑名單上
  • 在網絡爬蟲裏,一個網址是否被訪問過
  • yahoo, gmail等郵箱垃圾郵件過濾功能

具體實現

布隆過濾器做爲一個成熟的過濾器,應該學會實現本身了.

啊,不對,是網上有許多的簡易版實現,代碼不到100行就能夠,所以這裏不貼代碼了.

我在項目中使用了google guava項目下的BloomFilter,挺好用的.

個人解決方案

1. hbase部分

hbase負責存儲用戶瀏覽記錄的原始數據,只保存用戶瀏覽的文章的id或者url,這裏以id爲例.

經過範圍查詢能夠得到name:huyanshi,history=[1,2,4,5,6]格式的數據.

2. redis部分

在這裏面使用redis,主要是考慮到,針對活躍用戶,及頻繁刷新的用戶,每次請求都全量從Hbase拉取數據,而後構造布隆過濾器,即時Hbase扛得住,我以爲這個構造過濾器的時間也太長了.所以使用redis對過濾器進行緩存.

在redis中存儲序列化後的布隆過濾器對象,時間爲30分鐘,30分鐘內用戶若是再次訪問,直接從redis中獲取過濾器,而後進行過濾操做.

3. 布隆過濾器部分

主要是添加以及查詢兩個操做,從hbase拿到數據以後,構造過濾器,而後對當前返回的10條內容進行判重.以後將新的10條內容加入過濾器,再次寫入redis.

流程圖

很久沒畫圖了,,,慌得一批.

完.





ChangeLog

2018-12-18 完成

以上皆爲我的所思所得,若有錯誤歡迎評論區指正。

歡迎轉載,煩請署名並保留原文連接。

聯繫郵箱:huyanshi2580@gmail.com

更多學習筆記見我的博客------>呼延十

相關文章
相關標籤/搜索