溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Redis中怎么實(shí)現(xiàn)一個布隆過濾器

發(fā)布時間:2021-08-02 15:46:15 來源:億速云 閱讀:150 作者:Leah 欄目:大數(shù)據(jù)

本篇文章為大家展示了Redis中怎么實(shí)現(xiàn)一個布隆過濾器,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

布隆過濾器的簡介

布隆過濾器(BloomFilter)是一個很長的二進(jìn)制向量和一系列隨機(jī)映射函數(shù),我們也可以簡單的理解為它是一個不怎么精確的set結(jié)構(gòu)。本質(zhì)上布隆過濾器是一種數(shù)據(jù)結(jié)構(gòu),比較巧妙的概率型數(shù)據(jù)結(jié)構(gòu)(probabilistic data structure),特點(diǎn)是高效地插入和查詢,可以用來告訴你 “某樣?xùn)|西一定不存在或者可能存在”。相比于傳統(tǒng)的List、Set、Map等數(shù)據(jù)結(jié)構(gòu),它更高效、占用空間更少,但是缺點(diǎn)是其返回的結(jié)果是概率性的,但是我們不必過于擔(dān)心它不夠精確,只要參數(shù)設(shè)置合理,它的精度可以控制到足夠的精確。

適用場景:

  • 大數(shù)據(jù)是否存在的問題,比如上述的刷抖音去重問題

  • 解決緩存擊穿問題,如果數(shù)據(jù)請求一直是一個不存在的內(nèi)容,那么它會越過緩存直接請求數(shù)據(jù)庫,造成緩存擊穿,布隆過濾器也可以解決此類問題

  • 解決爬蟲爬到重復(fù)url內(nèi)容等等

布隆過濾器基本使用

布隆過濾器有二個基本指令,bf.add添加元素,bf.exists查詢元素是否存在,它的用法和set集合的sadd和sismember差不多。注意bf.add只能一次添加一個元素,如果想要一次添加多個,就需要用到bf.madd指令。同樣如果需要一次查詢多個元素是否存在,就需要用到bf.mexists指令。

> bf.add user user1(integer) 1> bf.add user user2(integer) 1> bf.add user user3(integer) 1> bf.exists user user1(integer) 1> bf.exists user user4(integer) 0> bf.madd user user4 user5 user61) (integer) 12) (integer) 13) (integer) 1> bf.mexists user user4 user5 user6 user71) (integer) 12) (integer) 13) (integer) 14) (integer) 0

上面使用的布隆過過濾器只是默認(rèn)參數(shù)的布隆過濾器,它在我們第一次add的時候自動創(chuàng)建。Redis也提供了可以自定義參數(shù)的布隆過濾器,只需要在add之前使用bf.reserve指令顯式創(chuàng)建就好了。如果對應(yīng)的key已經(jīng)存在,bf.reserve會報錯。bf.reserve有三個參數(shù),分別是key、error_rate(錯誤率)和initial_size:
error_rate越低,需要的空間越大
initial_size表示預(yù)計(jì)放入的元素數(shù)量,當(dāng)實(shí)際數(shù)量超過這個值時,誤判率就會提升,所以需要提前設(shè)置一個較大的數(shù)值避免超出導(dǎo)致誤判率升高;
如果不適用bf.reserve,默認(rèn)的error_rate是0.01,默認(rèn)的initial_size是100。

布隆過濾器的實(shí)現(xiàn)原理  

add操作

Redis中怎么實(shí)現(xiàn)一個布隆過濾器

每個布隆過濾器對應(yīng)到Redis的數(shù)據(jù)結(jié)構(gòu)里面就是一個大型的位數(shù)組和幾個不一樣的無偏 hash 函數(shù)。所謂無偏就是能夠把元素的 hash 值算得比較均勻。向布隆過濾器中添加key時,會使用多個hash函數(shù)對key進(jìn)行hash算得一個整數(shù)索引值然后對位數(shù)組長度進(jìn)行取模運(yùn)算得到一個位置,每個hash函數(shù)都會算得一個不同的位置。再把位數(shù)組的這幾個位置都置為1就完成了add操作。

exists操作

Redis中怎么實(shí)現(xiàn)一個布隆過濾器

exists操作跟add一樣,也會把hash的幾個位置都算出來,看看位數(shù)組中這幾個位置是否都是1,只要有一個位為0,那么說明布隆過濾器中這個key不存在。如果都是1,這并不能說明這個key就一定存在,只是極有可能存在,因?yàn)檫@些位被置為1可能是因?yàn)槠渌膋ey存在所致。

如果這個位數(shù)組比較稀疏,這個概率就會很大,如果這個位數(shù)組比較擁擠,這個概率就會降低。使用時不要讓實(shí)際元素遠(yuǎn)大于初始化大小,當(dāng)實(shí)際元素開始超出初始化大小時,應(yīng)該對布隆過濾器進(jìn)行重建,重新分配一個size更大的過濾器,再將所有的歷史元素批量add進(jìn)去 (這就要求我們在其它的存儲器中記錄所有的歷史元素)。因?yàn)閑rror_rate不會因?yàn)閿?shù)量超出就急劇增加,這就給我們重建過濾器提供了較為寬松的時間。

空間占用估算
計(jì)算公式:k=0.7*(l/n)          #約等于f=0.6185^(l/n)       #^表示次方計(jì)算,也就是 math.pow

布隆過濾器有兩個參數(shù),第一個是預(yù)計(jì)元素的數(shù)量n,第二個是錯誤率f。公式根據(jù)這兩個輸入得到兩個輸出,第一個輸出是位數(shù)組的長度l,也就是需要的存儲空間大小(bit),第二個輸出是hash函數(shù)的最佳數(shù)量k。hash函數(shù)的數(shù)量也會直接影響到錯誤率,最佳的數(shù)量會有最低的錯誤率。

從公式中可以看出

  • 1.位數(shù)組相對越長(l/n),錯誤率f越低,這個和直觀上理解是一致的

  • 位數(shù)組相對越長(l/n),hash函數(shù)需要的最佳數(shù)量也越多,影響計(jì)算效率

  • 當(dāng)一個元素平均需要1個字節(jié)(8bit)的指紋空間時(l/n=8),錯誤率大約為 2%

錯誤率
一個元素所需平均空間
空間數(shù)
10%4.792個bit5bit
1%9.585個bit10bit
0.1%14.377個bit15bit

有人會問如果實(shí)際的元素超過了預(yù)算元素,錯誤率會如何變化,會不會錯誤率非常高?我們引入一個公式

f=(1-0.5^t)^k#極限近似, k 是 hash 函數(shù)的最佳數(shù)量#t表示實(shí)際元素和預(yù)計(jì)元素的倍數(shù)

Redis中怎么實(shí)現(xiàn)一個布隆過濾器

錯誤率為 10% 時,倍數(shù)比為 2 時,錯誤率就會升至接近 40%
錯誤率為 1% 時,倍數(shù)比為 2 時,錯誤率升至 15%
錯誤率為 0.1%,倍數(shù)比為 2 時,錯誤率升至 5%

上述內(nèi)容就是Redis中怎么實(shí)現(xiàn)一個布隆過濾器,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI