導航:首頁 > 凈水問答 > 布隆過濾器使用

布隆過濾器使用

發布時間:2023-03-14 03:54:53

A. 布隆過濾

[TOC]

通過解決方案:

Java中如將數據存儲在內存中,最簡單的演算法結構是HashMap。通過HashMap判斷key是否存在,來判斷數據是否存在。通過hash演算法查找元素,時間復雜度基本是 O(1) (可能存在hash沖突後轉換成鏈表或紅黑樹的情況,時間復雜度的影響可以忽略)。

使用HashMap速度很快,存儲簡單,絕大部分場景可以使用。但是HashMap 佔用的空間比較大 :

為什麼出現布隆過濾器:

舉例:

如1000萬個Integer存儲在內存中,佔用空間為:4x32x10000000位,即1220兆。如布隆過濾器通過4位元組存儲(布隆過濾器通過多次hash對數據計算後-->幾次hash根據數據量指定,得到多個數據, 佔用多個位 ),則佔用空間為610M。比原有空間少一半。

個人覺得,此比較在字元等的比較中尤為有效。
一個字元串多個字元,根據編碼方式,一個字元兩個或三個位元組,如10個字元,字元串存儲佔用20個位元組,還有相關字元串相關的類信息的內存佔用。
位存儲,根據數據量的大小,hash的位數,靈活計算。如4個位元組,則是原hashMap佔用空間的五分之一。

(1)定義位元組向量

先定義一個指定長度的位元組數組(位元組數組,數組內每個元素的值)。

如長度為8(一個位元組大小),默認所有元素值均為0,如下:

(2)計算哈希值

將要寫入過濾器的數據,根據一定數量的哈希函數,得到多個哈希值,再依次判斷每個哈希值對應的索引。

如使用3個哈希函數,計算得到3個哈希值,判定哈希值對應的位元組向量為為1,3,7。

(3)更新位元組向量

將計算出的位元組向量的索引, 對應的位元組向量中的元素值更高為1 (無論之前為0或者為1,均更改為1)。如下:

(1)計算哈希值

將要判斷過濾器中是否存在的數據,根據一定數量的哈希函數,得到多個哈希值,再依次判斷每個哈希值對應的索引。

如使用3個哈希函數,計算得到3個哈希值,判定哈希值對應的位元組向量為為1,3,7。

注意:哈希函數的判斷方式和計算索引的方式,需和寫入數據時完全一致。

(2)判斷是否存在

如原位元組數組中,對應1,3,7中存在的元素的值都為1。則判定為此元素 可能存在 ,但凡有一個元素的值不為1,則判定此元素 一定不存在 。

布隆過濾器,主要需實現的目標是, 在指定的數據個數范圍內,滿足誤判率在設定的范圍內 ,誤判率太高的話,無法起到過濾數據的情況,誤判率不能為0。

因此需要計算兩個數據來滿足 存儲數據的個數 和 誤判率 :

使用布隆過濾器的決定性因素之一,就是此演算法插入數據和查詢數據的速度必須非常快。因此在對數據進行哈希運算的時候, 需選擇計算快的哈希演算法 。

而且, 寫入數據以及查詢數據的哈希演算法,順序和演算法都需完全一致 。

待完善。。。。。

可以通過google的 guava ,在內存中輕松實現布隆過濾器。

無需手動計算滿足位元組數組的長度和哈希個數,只需要輸入 擬輸入數據的個數 和 期望誤判率 即可。

不輸入期望誤判率的情況下,誤判率為0.03,即100個非范圍內的數據進行校驗時,約三個數據會判定為存在。

多次執行,結果一致,根據結果判定:

內存的存儲存在局限性,可以使用redis中的bitMap來實現位元組數組的存儲。

使用redis實現布隆過濾器。需要根據公式,手動計算位元組數組的長度和哈希的個數。

實現過程,待完善。。。。。。

B. 藉助Redis Bitmap實現簡單的布隆過濾器

在之前的 一篇文章 中,我們已經深入理解了布隆過濾器的基本原理,並且了解到它在緩存系統中有較多的應用。Redis提供的Bitmap正好能夠作為布隆過濾器所需要的位數組的基礎,本文先簡要介紹Bitmap,然後給出基於它的布隆過濾器實現。

Bitmap在Redis中並不是一個單獨的數據類型,而是由字元串類型(Redis內部稱Simple Dynamic String,SDS)之上定義的與比特相關的操作實現的,此時SDS就被當做位數組了。下面是在redis-cli中使用getbit和setbit指令的操作示例。

Redis的Bitmap是自動擴容的,亦即get/set到高位時,就會主動填充0。此外,還有bitcount指令用於計算特定位元組范圍內1的個數,bitop指令用來執行位運算(支持and、or、xor和not)。相應的用法可以查詢Redis官方文檔等。

下面我們基於Redis(Codis)實現布隆過濾器RedisBloomFilter。根據之前講解布隆過濾器的文章,要初始化一個布隆過濾器的話,需要兩個參數:預估的元素數量,以及可接受的最大誤差(即假陽性率)。另外,我們也需要傳入Jodis的連接池實例JedisResourcePool,以方便在Redis上操作。RedisBloomFilter類的成員和構造方法如下所示。

為了區分出布隆過濾器對應的Key,在原始Key的前面都加上"bf:"前綴。Bitmap長度bitmapLength和哈希函數個數numHashFunctions則利用Guava版實現中的方法來計算。

然後,我們需要計算一個元素被k個哈希函數散列後,對應到Bitmap的哪些比特上。這里仍然借鑒了Guava的BloomFilterStrategies實現,採用MurmurHash和雙重哈希進行散列。為了應用簡單,假設所有元素固定為字元串類型,不用泛型。

然後我們就可以通過Jedis的setbit()和getbit()方法來實現向布隆過濾器中插入元素與查詢元素是否存在的邏輯了。一個元素會對應多個比特,為了提高效率,流水線就派上用場了。另外,setbit指令不會重置對應Key的過期時間戳。

完畢,寫個簡單的單元測試吧。假設現在用布隆過濾器來存儲已讀帖子的ID,Key中包含用戶ID和時間。每天預估的每用戶最大閱讀量是3000篇,最大誤差3%。

觀察輸出。

C. 布隆過濾器詳解

布隆過濾器 (英語:Bloom Filter)是 1970 年由布隆提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數。主要用於判斷一個元素是否在一個集合中。

通常我們會遇到很多要判斷一個元素是否在某個集合中的業務場景,一般想到的是將集合中所有元素保存起來,然後通過比較確定。鏈表、樹、散列表(又叫哈希表,Hash table)等等數據結構都是這種思路。但是隨著集合中元素的增加,我們需要的存儲空間也會呈現線性增長,最終達到瓶頸。同時檢索速度也越來越慢,上述三種結構的檢索時間復雜度分別為 , , 。

這個時候,布隆過濾器(Bloom Filter)就應運而生。

了解布隆過濾器原理之前,先回顧下 Hash 函數原理。

哈希函數的概念是:將任意大小的輸入數據轉換成特定大小的輸出數據的函數,轉換後的數據稱為哈希值或哈希編碼,也叫散列值。下面是一幅示意圖:

所有散列函數都有如下基本特性:

但是用 hash表存儲大數據量時,空間效率還是很低,當只有一個 hash 函數時,還很容易發生哈希碰撞。

BloomFilter 是由一個固定大小的二進制向量或者點陣圖(bitmap)和一系列映射函數組成的。

在初始狀態時,對於長度為 m 的位數組,它的所有位都被置為0,如下圖所示:

當有變數被加入集合時,通過 K 個映射函數將這個變數映射成點陣圖中的 K 個點,把它們置為 1(假定有兩個變數都通過 3 個映射函數)。

查詢某個變數的時候我們只要看看這些點是不是都是 1 就可以大概率知道集合中有沒有它了

為什麼說是可能存在,而不是一定存在呢?那是因為映射函數本身就是散列函數,散列函數是會有碰撞的。

布隆過濾器的誤判是指多個輸入經過哈希之後在相同的bit位置1了,這樣就無法判斷究竟是哪個輸入產生的,因此誤判的根源在於相同的 bit 位被多次映射且置 1。

這種情況也造成了布隆過濾器的刪除問題,因為布隆過濾器的每一個 bit 並不是獨占的,很有可能多個元素共享了某一位。如果我們直接刪除這一位的話,會影響其他的元素。(比如上圖中的第 3 位)

相比於其它的數據結構,布隆過濾器在空間和時間方面都有巨大的優勢。布隆過濾器存儲空間和插入/查詢時間都是常數 ,另外,散列函數相互之間沒有關系,方便由硬體並行實現。布隆過濾器不需要存儲元素本身,在某些對保密要求非常嚴格的場合有優勢。

布隆過濾器可以表示全集,其它任何數據結構都不能;

但是布隆過濾器的缺點和優點一樣明顯。誤算率是其中之一。隨著存入的元素數量增加,誤算率隨之增加。但是如果元素數量太少,則使用散列表足矣。

另外,一般情況下不能從布隆過濾器中刪除元素。我們很容易想到把位數組變成整數數組,每插入一個元素相應的計數器加 1, 這樣刪除元素時將計數器減掉就可以了。然而要保證安全地刪除元素並非如此簡單。首先我們必須保證刪除的元素的確在布隆過濾器裡面。這一點單憑這個過濾器是無法保證的。另外計數器回繞也會造成問題。

在降低誤算率方面,有不少工作,使得出現了很多布隆過濾器的變種。

在程序的世界中,布隆過濾器是程序員的一把利器,利用它可以快速地解決項目中一些比較棘手的問題。

如網頁 URL 去重、垃圾郵件識別、大集合中重復元素的判斷和緩存穿透等問題。

布隆過濾器的典型應用有:

知道了布隆過濾去的原理和使用場景,我們可以自己實現一個簡單的布隆過濾器

分布式環境中,布隆過濾器肯定還需要考慮是可以共享的資源,這時候我們會想到 Redis,是的,Redis 也實現了布隆過濾器。

當然我們也可以把布隆過濾器通過 bloomFilter.writeTo() 寫入一個文件,放入OSS、S3這類對象存儲中。

Redis 提供的 bitMap 可以實現布隆過濾器,但是需要自己設計映射函數和一些細節,這和我們自定義沒啥區別。

Redis 官方提供的布隆過濾器到了 Redis 4.0 提供了插件功能之後才正式登場。布隆過濾器作為一個插件載入到 Redis Server 中,給 Redis 提供了強大的布隆去重功能。

在已安裝 Redis 的前提下,安裝 RedisBloom,有兩種方式

直接編譯進行安裝

使用Docker進行安裝

使用

布隆過濾器基本指令:

我們只有這幾個參數,肯定不會有誤判,當元素逐漸增多時,就會有一定的誤判了,這里就不做這個實驗了。

上面使用的布隆過濾器只是默認參數的布隆過濾器,它在我們第一次 add 的時候自動創建。

Redis 還提供了自定義參數的布隆過濾器, bf.reserve 過濾器名 error_rate initial_size

但是這個操作需要在 add 之前顯式創建。如果對應的 key 已經存在,bf.reserve 會報錯

我是一名 Javaer,肯定還要用 Java 來實現的,Java 的 Redis 客戶端比較多,有些還沒有提供指令擴展機制,筆者已知的 Redisson 和 lettuce 是可以使用布隆過濾器的,我們這里用 Redisson

為了解決布隆過濾器不能刪除元素的問題,布穀鳥過濾器橫空出世。論文《Cuckoo Filter:Better Than Bloom》作者將布穀鳥過濾器和布隆過濾器進行了深入的對比。相比布穀鳥過濾器而言布隆過濾器有以下不足:查詢性能弱、空間利用效率低、不支持反向操作(刪除)以及不支持計數。

由於使用較少,暫不深入。

https://www.cs.cmu.e/~dga/papers/cuckoo-conext2014.pdf

http://www.justdojava.com/2019/10/22/bloomfilter/

https://www.cnblogs.com/cpselvis/p/6265825.html

https://juejin.im/post/5cc5aa7ce51d456e431adac5

D. redis布隆過濾器拆分長度

布隆過濾器是一種類似set的數據結構。

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_rate和 capacity都需要設置一個合適的數值。

閱讀全文

與布隆過濾器使用相關的資料

熱點內容
哈弗h6工廠濾芯怎麼拆 瀏覽:371
原神純水精靈怎麼捕捉 瀏覽:109
純水之球各伺服器多少g 瀏覽:448
格卡諾空氣凈化器怎麼重置 瀏覽:686
飲水機濾芯怎麼驗貨 瀏覽:385
華帝凈水器售後電話多少 瀏覽:681
里水污水處理後排到哪裡 瀏覽:6
污水攻堅補齊什麼短板 瀏覽:446
跑污水處理跑業務工資高嗎 瀏覽:894
河南工業污水處理 瀏覽:871
污水處理廠進水檢測標准 瀏覽:102
天劍摩托車125怎麼換機油濾芯 瀏覽:846
污水處理廠斜管套什麼定額 瀏覽:129
三菱歐藍德空調濾芯怎麼拆換 瀏覽:386
污水流樓底下怎麼處理 瀏覽:869
汽油濾芯是什麼表現 瀏覽:433
污水消毒處理工藝有哪些 瀏覽:887
硬水垢清除 瀏覽:360
過濾過程的推動力 瀏覽:415
ps怎麼把污水處理成清澈 瀏覽:418