Redis高級(jí)功能之 - 布隆過濾器

從一個(gè)場(chǎng)景說(shuō)起

在刷抖音有刷到過重復(fù)內(nèi)容嗎,這么多的推薦內(nèi)容要推薦給這么多的用戶赚哗,它是怎么保證每個(gè)用戶在看推薦內(nèi)容時(shí)蟋字,保證不會(huì)出現(xiàn)之前已經(jīng)看過的推薦視頻呢?也就是說(shuō)嗅钻,抖音是如何實(shí)現(xiàn) 推送去重 的呢皂冰。

傳統(tǒng)實(shí)現(xiàn)上,可能是服務(wù)器記錄了每個(gè)用戶看過的所有歷史記錄养篓,當(dāng)推薦系統(tǒng)推薦短視頻時(shí)會(huì)從每個(gè)用戶的歷史記錄里進(jìn)行 篩選秃流,過濾掉那些已經(jīng)存在的記錄。問題是當(dāng)用戶量很大柳弄,每個(gè)用戶看過的短視頻又很多的情況下舶胀,這種方式,推薦系統(tǒng)的去重工作 在性能上是跟不上的。

如果歷史記錄存儲(chǔ)在關(guān)系數(shù)據(jù)庫(kù)里嚣伐,去重就需要頻繁地對(duì)數(shù)據(jù)庫(kù)進(jìn)行 exists 查詢糖赔,當(dāng)系統(tǒng)并發(fā)量很高時(shí),數(shù)據(jù)庫(kù)是很難抗住壓力的轩端。

如果使用緩存放典,但是這么多用戶這么多的歷史記錄,如果全部緩存起來(lái)基茵,那得需要浪費(fèi)多大的空間奋构,并且這個(gè)存儲(chǔ)空間會(huì)隨著時(shí)間呈線性增長(zhǎng),撐不了多久耿导,不緩存性能又跟不上声怔。

布隆過濾器(Bloom Filter) 就是這樣一種專門用來(lái)解決去重問題的高級(jí)數(shù)據(jù)結(jié)構(gòu),類似于bit數(shù)組舱呻,有那么一點(diǎn)不精確醋火,也存在一定的誤判概率,但它能在解決去重的同時(shí)箱吕,在 空間上能節(jié)省 90% 以上芥驳,也是非常值得的。

簡(jiǎn)介

布隆過濾器(Bloom Filter實(shí)際上 是一個(gè)很長(zhǎng)的二進(jìn)制向量和一系列隨機(jī)映射函數(shù) 茬高,實(shí)際上你也可以把它 簡(jiǎn)單理解 為一個(gè)不怎么精確的 set 結(jié)構(gòu)兆旬,當(dāng)你使用它的 contains 方法判斷某個(gè)對(duì)象是否存在時(shí),它可能會(huì)誤判怎栽。但是布隆過濾器也不是特別不精確丽猬,只要參數(shù)設(shè)置的合理,它的精確度可以控制的相對(duì)足夠精確熏瞄,只會(huì)有小小的誤判概率脚祟。

當(dāng)布隆過濾器說(shuō)某個(gè)值存在時(shí),這個(gè)值可能不存在强饮;當(dāng)它說(shuō)不存在時(shí)由桌,那么一定不存在。

原理

當(dāng)一個(gè)元素被加入集合時(shí)邮丰,通過N個(gè)散列函數(shù)將這個(gè)元素映射成一個(gè)位數(shù)組中的N個(gè)點(diǎn)行您,把它們置為1。檢索時(shí)剪廉,我們只要看看這些點(diǎn)是不是都是1就(大約)知道集合中有沒有它了:如果這些點(diǎn)有任何一個(gè)0娃循,則被檢元素一定不在;如果都是1斗蒋,則被檢元素很可能在淮野。這就是布隆過濾器的基本思想捧书。

Bloom Filter跟單哈希函數(shù)Bit-Map不同之處在于:Bloom Filter使用了N個(gè)哈希函數(shù),每個(gè)字符串跟N個(gè)bit對(duì)應(yīng)骤星。從而降低了沖突的概率。


image.png

簡(jiǎn)單的說(shuō)一下就是我們先把我們數(shù)據(jù)庫(kù)的數(shù)據(jù)都加載到我們的過濾器中爆哑,比如數(shù)據(jù)庫(kù)的id現(xiàn)在有:1洞难、2、3
那就用id:1 為例子他在上圖中經(jīng)過三次hash之后揭朝,把三次原本值0的地方改為1
下次我進(jìn)來(lái)查詢?nèi)绻鹖d也是1 那我就把1拿去三次hash 發(fā)現(xiàn)跟上面的三個(gè)位置完全一樣队贱,那就能證明過濾器中有1的,反之如果不一樣就說(shuō)明不存在了潭袱。

缺點(diǎn)

bloom filter之所以能做到在時(shí)間和空間上的效率比較高柱嫌,是因?yàn)闋奚伺袛嗟臏?zhǔn)確率、刪除的便利性

  • 存在誤判屯换,可能要查到的元素并沒有在容器中编丘,但是hash之后得到的n個(gè)位置上值都是1。如果bloom filter中存儲(chǔ)的是黑名單彤悔,那么可以通過建立一個(gè)白名單來(lái)存儲(chǔ)可能會(huì)誤判的元素嘉抓。

  • 刪除困難。一個(gè)放入容器的元素映射到bit數(shù)組的n個(gè)位置上是1晕窑,刪除的時(shí)候不能簡(jiǎn)單的直接置為0抑片,可能會(huì)影響其他元素的判斷。

應(yīng)用場(chǎng)景

  • 解決緩存穿透:我們經(jīng)常會(huì)把一些熱點(diǎn)數(shù)據(jù)放在 Redis 中當(dāng)作緩存杨赤,例如產(chǎn)品詳情敞斋。通常一個(gè)請(qǐng)求過來(lái)之后我們會(huì)先查詢緩存,而不用直接讀取數(shù)據(jù)庫(kù)疾牲,這是提升性能最簡(jiǎn)單也是最普遍的做法植捎,但是 如果一直請(qǐng)求一個(gè)不存在的緩存,那么此時(shí)一定不存在緩存说敏,那就會(huì)有大量請(qǐng)求直接打到數(shù)據(jù)庫(kù) 上鸥跟,造成 緩存穿透,布隆過濾器也可以用來(lái)解決此類問題盔沫。

  • 大數(shù)據(jù)判斷是否存在:這就可以實(shí)現(xiàn)出上述的去重功能医咨,如果你的服務(wù)器內(nèi)存足夠大的話,那么使用 HashMap 可能是一個(gè)不錯(cuò)的解決方案架诞,理論上時(shí)間復(fù)雜度可以達(dá)到 O(1)的級(jí)別拟淮,但是當(dāng)數(shù)據(jù)量起來(lái)之后,還是只能考慮布隆過濾器谴忧。場(chǎng)景有例如爬蟲過濾已抓到的url就不再抓很泊,可用bloom filter過濾角虫;前面說(shuō)的存儲(chǔ)用戶看過的視頻記錄; 垃圾郵件過濾等委造。

  • 垃圾郵件過濾戳鹅。如果用哈希表,每存儲(chǔ)一億個(gè) email地址昏兆,就需要 1.6GB的內(nèi)存(用哈希表實(shí)現(xiàn)的具體辦法是將每一個(gè) email地址對(duì)應(yīng)成一個(gè)八字節(jié)的信息指紋枫虏,然后將這些信息指紋存入哈希表,由于哈希表的存儲(chǔ)效率一般只有 50%爬虱,因此一個(gè) email地址需要占用十六個(gè)字節(jié)隶债。一億個(gè)地址大約要 1.6GB,即十六億字節(jié)的內(nèi)存)跑筝。因此存貯幾十億個(gè)郵件地址可能需要上百 GB的內(nèi)存死讹。而Bloom Filter只需要哈希表 1/8到 1/4 的大小就能解決同樣的問題。

Redis中使用

Redis 官方 提供的布隆過濾器到了 Redis 4.0 提供了插件功能之后才正式登場(chǎng)曲梗。布隆過濾器作為一個(gè)插件加載到 Redis Server 中赞警,給 Redis 提供了強(qiáng)大的布隆去重功能。

實(shí)驗(yàn)

布隆過濾器有兩個(gè)基本指令稀并,bf.add 添加元素仅颇,bf.exists 查詢?cè)厥欠翊嬖冢挠梅ê?set 集合的 sadd 和 sismember 差不多碘举。注意 bf.add 只能一次添加一個(gè)元素忘瓦,如果想要一次添加多個(gè),就需要用到 bf.madd 指令引颈。同樣如果需要一次查詢多個(gè)元素是否存在耕皮,就需要用到 bf.mexists 指令。

127.0.0.1:6379> bf.add bl user1
(integer) 1
127.0.0.1:6379> bf.add bl user2
(integer) 1
127.0.0.1:6379> bf.add bl user3
(integer) 1
127.0.0.1:6379> bf.exists bl user1
(integer) 1
127.0.0.1:6379> bf.exists bl user2
(integer) 1
127.0.0.1:6379> bf.exists bl user3
(integer) 1
127.0.0.1:6379> bf.exists bl user4
(integer) 0
127.0.0.1:6379> bf.madd bl user4 user5 user6
1) (integer) 1
2) (integer) 1
3) (integer) 1
127.0.0.1:6379> bf.mexists bl user4 user5 user6 user7
1) (integer) 1
2) (integer) 1
3) (integer) 1
4) (integer) 0
127.0.0.1:6379> object encoding bl
"raw"
127.0.0.1:6379> type bl
MBbloom--
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蝙场,一起剝皮案震驚了整個(gè)濱河市凌停,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌售滤,老刑警劉巖罚拟,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異完箩,居然都是意外死亡赐俗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門弊知,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)阻逮,“玉大人,你說(shuō)我怎么就攤上這事秩彤∈宥螅” “怎么了事哭?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)瓜富。 經(jīng)常有香客問我鳍咱,道長(zhǎng),這世上最難降的妖魔是什么食呻? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任流炕,我火速辦了婚禮,結(jié)果婚禮上仅胞,老公的妹妹穿的比我還像新娘。我一直安慰自己剑辫,他們只是感情好干旧,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妹蔽,像睡著了一般椎眯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胳岂,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天编整,我揣著相機(jī)與錄音,去河邊找鬼乳丰。 笑死掌测,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的产园。 我是一名探鬼主播汞斧,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼什燕!你這毒婦竟也來(lái)了粘勒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤屎即,失蹤者是張志新(化名)和其女友劉穎庙睡,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體技俐,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乘陪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了虽另。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暂刘。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖捂刺,靈堂內(nèi)的尸體忽然破棺而出谣拣,到底是詐尸還是另有隱情募寨,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布森缠,位于F島的核電站拔鹰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏贵涵。R本人自食惡果不足惜列肢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宾茂。 院中可真熱鬧瓷马,春花似錦、人聲如沸跨晴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)端盆。三九已至怀骤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間焕妙,已是汗流浹背蒋伦。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留焚鹊,地道東北人痕届。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像寺旺,于是被迫代替她去往敵國(guó)和親爷抓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 之前阻塑,小馬在聊緩存擊穿和穿透的文中有介紹過防止緩存穿透其中的一種方式是使用布隆過濾器蓝撇,那什么是布隆過濾器呢?今天就...
    小馬過河R閱讀 453評(píng)論 0 5
  • 簡(jiǎn)介 英語(yǔ):(Bloom Filter)是 1970 年由布隆提出的陈莽。它實(shí)際上是一個(gè)很長(zhǎng)的二進(jìn)制向量和一系列隨機(jī)映...
    zzj0990閱讀 829評(píng)論 0 10
  • 轉(zhuǎn)載于詳細(xì)解析Redis中的布隆過濾器及其應(yīng)用 - 萬(wàn)貓學(xué)社 - 博客園[https://www.cnblogs....
    愛健身的兔子閱讀 427評(píng)論 0 1
  • 表情是什么渤昌,我認(rèn)為表情就是表現(xiàn)出來(lái)的情緒。表情可以傳達(dá)很多信息走搁。高興了當(dāng)然就笑了独柑,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,356評(píng)論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者私植,不喜歡去冒險(xiǎn)忌栅,但是人生放棄了冒險(xiǎn),也就放棄了無(wú)數(shù)的可能曲稼。 ...
    yichen大刀閱讀 6,059評(píng)論 0 4