redis的分佈式布隆過濾器 問題 布隆過濾器 布隆過濾器原理 布隆過濾器誤差 Redis布隆過濾器的基本使用 布隆過濾器的高級使用 布隆過濾器的應用 總結

問題

老顧先來舉個常會問到的面試題:現有50億個電話號碼,現有10萬個電話號碼,如何要快速準確的判斷這些電話號碼是否已經存在?

上面的問題可以細化一下,也就是50億個電話號碼在數據庫中,現在要快速、準確的判斷提供的10萬個電話號碼是否存在。

我們小夥伴們是否腦子中會有以下方案:

實際項目中也會遇到類似的問題,如垃圾郵件過濾、網絡爬蟲重複url檢測等,本質就是判斷數據存不存在一個大的集合中。

那如何去解決呢?這就是我們今天老顧要介紹的布隆過濾器方案,我們繼續往下看。

布隆過濾器

布隆過濾器是一種類似set的數據結構,只是不太準確,當判斷元素是否存在時返回結果存在但真實不一定存在;當返回不存在時肯定是不存在,所以判斷去重時有一定的誤判概率。

當然,誤判只會發生在過濾器沒有添加過的元素,對於添加過的元素不會發生誤判。

特點:高效地插入和查詢,佔用空間少,返回的結果是不確定性的。

布隆過濾器原理

這個是由柏頓.布隆在1970年提出,用很小的空間,解決上述的類似問題。

實現原理就是我們需要一個很長的二進制數組(也叫向量);在添加數據時,使用多個hash函數對key進行hash運算得到一個索引值(即二進制數組的索引值)

上圖中,下面是很長的二進制數組,第二層就是多個hash函數,再上面就是數據。

上圖中,每個數據經過多個hash函數計算,得到索引值,並把二進制數組對應的索引值那邊設置爲1,我們發現經過三次hash就會在三個索引的地方設置爲1,也就是代表此數據存在。

布隆過濾器誤差

空間佔用

布隆過濾器的空間佔用有一個簡單的計算公式,但推導比較繁瑣。布隆過濾器有兩個參數,預計元素數量n,錯誤率f,公式得到兩個輸出,位數組長度L(即存儲空間大小bit),hash函數的最佳數量k。

k = 0.7*(1/n)
f = 0.6185^(L/n)

實際元素超出時

以上小夥伴們只要知道會存在誤差就行了,不需要強求是怎麼計算的。

Redis布隆過濾器的基本使用

在Redis中,布隆過濾器有兩個基本命令,分別是:

  • bf.add添加元素到布隆過濾器中,類似於集合的sadd命令,不過bf.add命令只能一次添加一個元素,如果想一次添加多個元素,可以使用bf.madd命令。

  • bf.exists判斷某個元素是否在過濾器中,類似於集合的sismember命令,不過bf.exists命令只能一次查詢一個元素,如果想一次查詢多個元素,可以使用bf.mexists命令。

布隆過濾器的高級使用

上面的例子中使用的布隆過濾器只是默認參數的布隆過濾器,它在我們第一次使用 bf.add 命令時自動創建的。Redis還提供了自定義參數的布隆過濾器,想要儘量減少布隆過濾器的誤判,就要設置合理的參數。

在使用 bf.add 命令添加元素之前,使用bf.reserve 命令創建一個自定義的布隆過濾器bf.reserve命令有三個參數,分別是:

  • key:鍵

  • error_rate:期望錯誤率,期望錯誤率越低,需要的空間就越大。

  • capacity:初始容量,當實際元素的數量超過這個初始化容量時,誤判率上升。

比如:

如果對應的key已經存在時,在執行bf.reserve命令就會報錯。如果不使用bf.reserve命令創建,而是使用Redis自動創建的布隆過濾器,默認的error_rate是 0.01,capacity是 100。

布隆過濾器的error_rate 越小,需要的存儲空間就越大,對於不需要過於精確的場景,error_rate設置稍大一點也可以。布隆過濾器的capacity設置的過大,會浪費存儲空間,設置的過小,就會影響準確率,所以在使用之前一定要儘可能地精確估計好元素數量,還需要加上一定的冗餘空間以避免實際元素可能會意外高出設置值很多。總之,error_ratecapacity都需要設置一個合適的數值。

布隆過濾器的應用

解決緩存穿透的問題

一般情況下,先查詢緩存是否有該條數據,緩存中沒有時,再查詢數據庫。當數據庫也不存在該條數據時,每次查詢都要訪問數據庫,這就是緩存穿透。緩存穿透帶來的問題是,當有大量請求查詢數據庫不存在的數據時,就會給數據庫帶來壓力,甚至會拖垮數據庫。

可以使用布隆過濾器解決緩存穿透的問題,把已存在數據的key存在布隆過濾器中。當有新的請求時,先到布隆過濾器中查詢是否存在,如果不存在該條數據直接返回;如果存在該條數據再查詢緩存查詢數據庫。

黑名單校驗

發現存在黑名單中的,就執行特定操作。比如:識別垃圾郵件,只要是郵箱在黑名單中的郵件,就識別爲垃圾郵件。假設黑名單的數量是數以億計的,存放起來就是非常耗費存儲空間的,布隆過濾器則是一個較好的解決方案。把所有黑名單都放在布隆過濾器中,再收到郵件時,判斷郵件地址是否在布隆過濾器中即可。

總結

今天老顧帶着大家瞭解了redis布隆過濾器的原理以及應用場景;希望能給小夥伴帶來幫助,謝謝!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章