Google布隆過濾器與Redis布隆過濾器詳解

一、什么是布隆過濾器箩溃?

布隆過濾器可以用來判斷一個元素是否在一個集合中瞭吃。它的優(yōu)勢是只需要占用很小的內(nèi)存空間以及有著高效的查詢效率。

對于布隆過濾器而言涣旨,它的本質(zhì)是一個位數(shù)組:位數(shù)組就是數(shù)組的每個元素都只占用1bit 歪架,并且每個元素只能是0或者1

布隆過濾器除了一個位數(shù)組,還有 K 個哈希函數(shù)开泽。當(dāng)一個元素加入布隆過濾器中的時候牡拇,會進(jìn)行如下操作:

  • 使用K個哈希函數(shù)對元素值進(jìn)行K次計算,得到K個哈希值
  • 根據(jù)得到的哈希值穆律,在位數(shù)組中把對應(yīng)下標(biāo)的值置為1

下圖表示有三個hash函數(shù),比如一個集合中有x导俘、y峦耘、z三個元素,分別用三個hash函數(shù)映射到二進(jìn)制序列的某些位上旅薄,假設(shè)我們判斷w是否在集合中辅髓,同樣用三個hash函數(shù)來映射,結(jié)果發(fā)現(xiàn)取得的結(jié)果不全為1少梁,則表示w不在集合里面洛口。


file

數(shù)組的容量即使再大,也是有限的凯沪。那么隨著元素的增加第焰,插入的元素就會越多,位數(shù)組中被置為1的位置因此也越多妨马,這就會造成一種情況:當(dāng)一個不在布隆過濾器中的元素挺举,經(jīng)過同樣規(guī)則的哈希計算之后,得到的值在位數(shù)組中查詢烘跺,有可能這些位置因?yàn)橹捌渌氐牟僮飨缺恢脼?了

所以湘纵,有可能一個不存在布隆過濾器中的會被誤判成在布隆過濾器中。這就是布隆過濾器的一個缺陷滤淳。但是梧喷,如果布隆過濾器判斷某個元素不在布隆過濾器中,那么這個值就一定不在布隆過濾器中∑痰校總結(jié)就是:

  • 布隆過濾器說某個元素在汇歹,可能會被誤判
  • 布隆過濾器說某個元素不在,那么一定不在

二适刀、Google布隆過濾器基本使用

  1. 引入依賴
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>21.0</version>
    </dependency>
  1. BloomFilterService

@Service
public class BloomFilterService {

@Autowired
private UserMapper userMapper;

private BloomFilter<Integer> bf;

/**
 * 創(chuàng)建布隆過濾器
 *
 * @PostConstruct:程序啟動時候加載此方法
 */
@PostConstruct
public void initBloomFilter() {
    List<User> userList = userMapper.selectAllUser();
    if (CollectionUtils.isEmpty(userList)) {
        return;
    }
    //創(chuàng)建布隆過濾器(默認(rèn)3%誤差)
    bf = BloomFilter.create(Funnels.integerFunnel(), userList.size());
    for (User user : userList) {
        bf.put(user.getId());
    }
}

/**
 * 判斷id可能存在于布隆過濾器里面
 *
 * @param id
 * @return
 */
public boolean userIdExists(int id) {
    return bf.mightContain(id);
}

}

  1. BloomFilterController

@RestController
public class BloomFilterController {

@Autowired
private BloomFilterService bloomFilterService;

@RequestMapping("/bloom/idExists")
public boolean ifExists(int id) {
    return bloomFilterService.userIdExists(id);
}

}

三秤朗、Google布隆過濾器與Redis布隆過濾器對比

  1. Google布隆過濾器的缺點(diǎn)

基于JVM內(nèi)存的一種布隆過濾器
重啟即失效
本地內(nèi)存無法用在分布式場景
不支持大數(shù)據(jù)量存儲

  1. Redis布隆過濾器

可擴(kuò)展性Bloom過濾器:一旦Bloom過濾器達(dá)到容量,就會在其上創(chuàng)建一個新的過濾器
不存在重啟即失效或者定時任務(wù)維護(hù)的成本:基于Google實(shí)現(xiàn)的布隆過濾器需要啟動之后初始化布隆過濾器
缺點(diǎn):需要網(wǎng)絡(luò)IO笔喉,性能比Google布隆過濾器低

四取视、Redis布隆過濾器安裝和基本使用

1)使用Docker安裝

[root@localhost ~]# docker run -d -p 6379:6379 --name bloomfilter redislabs/rebloom

2)基本使用

[root@localhost ~]# docker exec -it bloomfilter /bin/bash
root@7a06a3528556:/data# redis-cli -p 6379
127.0.0.1:6379>

Redis布隆過濾器命令:

bf.add:添加元素到布隆過濾器中,只能添加一個元素常挚,如果想要添加多個使用bf.madd命令
bf.exists:判斷某個元素是否在過濾器中作谭,只能判斷一個元素,如果想要判斷多個使用bf.mexists

127.0.0.1:6379> bf.add urls www.taobao.com
(integer) 1
127.0.0.1:6379> bf.exists urls www.taobao.com
(integer) 1
127.0.0.1:6379> bf.madd urls www.baidu.com www.tianmao.com

  1. (integer) 1
  2. (integer) 1
    127.0.0.1:6379> bf.mexists urls www.baidu.com www.tianmao.com
  3. (integer) 1
  4. (integer) 1

上面使用的布隆過濾器只是默認(rèn)參數(shù)的布隆過濾器奄毡,它在我們第一次add的時候自動創(chuàng)建折欠。Redis還提供了自定義參數(shù)的布隆過濾器,需要在add之前使用bf.reserve指令顯式創(chuàng)建吼过。如果對應(yīng)的key已經(jīng)存在锐秦,bf.reserve會報錯(error) ERR item exists bf.reserve 過濾器名 error_rate initial_size

布隆過濾器存在誤判的情況,在Redis中有兩個值決定布隆過濾器的準(zhǔn)確率:

  • error_rate:允許布隆過濾器的錯誤率盗忱,這個值越低過濾器的位數(shù)組的大小越大酱床,占用空間也就越大
  • initial_size:布隆過濾器可以儲存的元素個數(shù),當(dāng)實(shí)際存儲的元素個數(shù)超過這個值之后趟佃,過濾器的準(zhǔn)確率會下降

127.0.0.1:6379> bf.reserve user 0.01 100

OK

五扇谣、會員轉(zhuǎn)盤抽獎

file

實(shí)現(xiàn)思路:在判斷用戶是否是會員的時候,第一步先通過布隆過濾器過濾掉99%的非會員(誤碼率為1%的情況下)闲昭,由于布隆過濾器有可能將一個不存在布隆過濾器中的誤判成在布隆過濾器中罐寨,也就是有可能會把非會員判斷為會員,所以第二步查詢數(shù)據(jù)庫中用戶對應(yīng)的數(shù)據(jù)庫信息判斷該用戶是否是會員

關(guān)注我的公眾號序矩,后臺回復(fù)【JAVAPDF】獲取200頁面試題鸯绿!
5萬人關(guān)注的大數(shù)據(jù)成神之路,不來了解一下嗎贮泞?
5萬人關(guān)注的大數(shù)據(jù)成神之路楞慈,真的不來了解一下嗎?
5萬人關(guān)注的大數(shù)據(jù)成神之路啃擦,確定真的不來了解一下嗎囊蓝?

歡迎您關(guān)注《大數(shù)據(jù)成神之路》
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市令蛉,隨后出現(xiàn)的幾起案子聚霜,更是在濱河造成了極大的恐慌狡恬,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝎宇,死亡現(xiàn)場離奇詭異弟劲,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)姥芥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門兔乞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凉唐,你說我怎么就攤上這事庸追。” “怎么了台囱?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵淡溯,是天一觀的道長。 經(jīng)常有香客問我簿训,道長咱娶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任强品,我火速辦了婚禮膘侮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘的榛。我一直安慰自己喻喳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布困曙。 她就那樣靜靜地躺著,像睡著了一般谦去。 火紅的嫁衣襯著肌膚如雪慷丽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天鳄哭,我揣著相機(jī)與錄音要糊,去河邊找鬼。 笑死妆丘,一個胖子當(dāng)著我的面吹牛锄俄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播勺拣,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼奶赠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了药有?” 一聲冷哼從身側(cè)響起毅戈,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤苹丸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后苇经,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赘理,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年扇单,在試婚紗的時候發(fā)現(xiàn)自己被綠了商模。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜘澜,死狀恐怖施流,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情兼都,我是刑警寧澤嫂沉,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站扮碧,受9級特大地震影響趟章,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜慎王,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一蚓土、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赖淤,春花似錦蜀漆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吐限,卻和暖如春鲜侥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诸典。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工描函, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人狐粱。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓舀寓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肌蜻。 傳聞我的和親對象是個殘疾皇子互墓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

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