java 布隆過濾器_什么是布隆過濾器(Bloom Filter)?

在日常工作中,有一個比較常見的需求,就是需要判斷一個元素是否在集合中。

例如以下場景:

  • 給定一個IP黑名單庫,檢查指定IP是否在黑名單中?

  • 在接收郵件的時候,判斷一個郵箱地址是否為垃圾郵件?

  • 在文字處理軟件中,檢查一個英文單詞是否拼寫正確?

遇到這種問題,通常直覺會告訴我們,應該使用集合這種數據結構來實現。例如,先將IP黑名單庫的所有IP全部存儲到一個集合中,然后再拿指定的IP到該集合中檢查是否存在,如果存在則說明該IP命中黑名單。

通過一段Java代碼,來模擬IP黑名單庫的存儲和檢查。

public class IPBlackList {

public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("192.168.1.1");
set.add("192.168.1.2");
set.add("192.168.1.4");
System.out.println(set.contains("192.168.1.1"));
System.out.println(set.contains("192.168.1.2"));
System.out.println(set.contains("192.168.1.3"));
System.out.println(set.contains("192.168.1.4"));
}

}

執行結果:

true
true
false
true

集合的內部,通常是使用散列表來實現。其優點是查詢非常高效,缺點是比較耗費存儲空間。

一般在數據量比較小的時候,我們會使用集合來進行存儲。以空間換時間,在占用空間較小的情況下,同時又能提高查詢效率。

但是,當存儲的數據量比較大的時候,耗費大量空間將會成為問題。因為這些數據通常會存儲到進程內存中,以加快查詢效率。而機器的內存通常都是有限的,要盡可能高效的使用。

另一方面,散列表在空間和效率上是需要做平衡的。存儲相同數量的元素,如果散列表容量越小,出現沖突的概率就越高,用于解決沖突的時間將會花費更多,從而影響性能。

而布隆過濾器(Bloom Filter)的產生,能夠很好的解決這個問題。一方面能夠以更少的內存來存儲數據,另一方面能夠實現非常高效的查詢性能。

布隆過濾器(Bloom Filter)

布隆過濾器(Bloom Filter)是一個數據結構,由布隆(Burton Howard Bloom)于1970年提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數。

布隆過濾器可以用于高效的檢索一個元素是否在一個集合中。它的優點是空間效率和查詢時間都遠遠優于一般的算法,缺點是有一定的誤識別率,而且難以刪除(一般不支持,需要額外的實現)。

布隆過濾器之所以高效,因為它是一個概率數據結構,它能確認元素肯定不在集合中,或者元素可能在集合中。之所以說是可能,是因為它有一定的誤識別率,使得無法100%確定元素一定在集合中。

基本原理

布隆過濾器的基本工作原理并不復雜,大致如下:

首先,建立一個二進制向量,并將所有位設置為0。

然后,選定K個散列函數,用于對元素進行K次散列,計算向量的位下標。

添加元素

當添加一個元素到集合中時,通過K個散列函數分別作用于元素,生成K個值作為下標,并對向量的相應位設置為1。

檢查元素

如果要檢查一個元素是否存在集合中,用同樣的散列方法,生成K個下標,并檢查向量的相應位是否全部是1。如果全為1,則該元素很可能在集合中;否則(只要有1個或以上的位為0),該元素肯定不在集合中。

這就是布隆過濾器的基本思想。

e404a8205252bab39a5bbdf9d0ccfb3f.png

一個簡單的例子

假設有一個布隆過濾器,容量是15位,使用2個哈希函數。

797e773337a76e79ddc49eb3ca1c0af5.png

添加一個字符串a,2次哈希得到下標為4和10,將4和10對應的位由0標記為1。

c8c2f209dc1b5a79c798edb0e3211f17.png

然后添加一個字符串b,2次哈希得到下標為11和11,將11對應的位由0標記為1。

c333dff8817c3e715ef0b33a8f8fa3ce.png

再添加一個字符串c,2次哈希得到下標為11和12,將11和12對應的位由0標記為1。

0677b83a73e54a686731c1b965174c95.png

最后,添加一個字符串sam,2次哈希得到下標為0和7,將0和7對應的位由0標記為1。

bbbe5eebe83c84f4935ae819218ef65c.png

上面,我們添加了4個字符串,每個字符串分別進行2次哈希,對應的2個位標記為1,最終被標記為1的共有6位而不是8位。

這說明,不同的元素,哈希后得到的位置是可能出現重疊的。如果元素越多,出現重疊的概率會更高。如果有2個元素出現重疊的位置,我們是無法判斷任一元素一定在集合中的。

如果要檢查一下元素是否存在集合中,只需要以相同的方法,進行2次哈希,將得到的2個下標在布隆過濾器中的相應位進行查找。如果對應的2位不是全部為1,則該元素肯定不在集合中。如果對應的2位全部為1,則說明該元素可能在集合中,也可能不存在。

例如,檢查字符串b是否存在集合中,哈希得到的2個下標都為11。檢查發現,11對應的位為1。但是,這并不能說明b一定在集合中。這是因為,字符串c哈希后的下標也包含11,有可能只是字符串c在集合中,而b卻不存在,這就是造成了誤識別,也稱為假陽性。

再檢查字符串foo,哈希得到的下標分別為8和13,對應的位都為0。因此,字符串foo肯定不在集合中。

數學原理

布隆過濾器背后的數學原理是:

兩個完全隨機的數字相沖突的概率很小,因此可以在很小的誤識別率條件下,用很少的空間存儲大量信息。

解決誤識別率的2種方法

白名單

解決誤識別率的常見方法,是建立一個較小的白名單,用來存儲那些可能被誤識別的數據。

以垃圾郵件過濾為例。假設我們有一個垃圾郵件庫,用于在接收郵件的時候過濾掉垃圾郵件。

這時可以先將這個垃圾郵件庫存儲到布隆過濾器中,當接收到郵件的時候,可以先通過布隆過濾器高效的過濾出大部分正常郵件。

而對于少部分命中(可能為)垃圾郵件的,其中有一部分可能為正常郵件。

再創建一個白名單庫,當在布隆過濾器中判斷可能為垃圾郵件時,通過查詢白名單來確認是否為正常郵件。

對于沒在白名單中的郵件,默認會被移動到垃圾箱。通過人工識別的方式,當發現垃圾箱中存在正常郵件的時候,將其移入白名單。

回源確認

很多時候,使用布隆過濾器是為了低成本,高效率的攔截掉大量數據不在集合中的場景。

例如:

  • Google Bigtable,Apache HBase以及Apache Cassandra和PostgreSQL 使用Bloom過濾器來減少對不存在的行或列的磁盤查找。避免進行昂貴的磁盤查找,可大大提高數據庫查詢操作的性能。

  • 在谷歌瀏覽器用于使用布隆過濾器來識別惡意URL的網頁瀏覽器。首先會針對本地Bloom過濾器檢查所有URL,只有在Bloom過濾器返回肯定結果的情況下,才對執行的URL進行全面檢查(如果該結果也返回肯定結果,則用戶會發出警告)。

  • 攔截掉大量非IP黑名單請求,對于少量可能在黑名單中的IP,再查詢一次黑名單庫。

這是布隆過濾器非常典型的應用場景,先過濾掉大部分請求,然后只處理少量不明確的請求。

這個方法,和白名單庫的區別是,不需要再另外建立一套庫來處理,而是使用本來就已經存在的數據和邏輯。

例如Google Bigtable查詢數據行本來就是需要查的,只不過使用布隆過濾器攔截掉了大部分不必要的請求。而IP是否為黑名單也是需要查詢的,同樣是先使用布隆過濾器來攔截掉大部分IP。

而上面垃圾郵件的處理,對于可能為垃圾郵件的情況,不是通過完整的垃圾郵件庫再查詢一次進行確認,而是用增加白名單來進行判斷的方式。因為通常來說,白名單庫會更小,便于緩存。

這里所說的回源,實際上是對可能被誤識別的請求,最后要回到數據源頭或邏輯確認一次。

參考

https://en.wikipedia.org/wiki/Bloom_filter

https://en.wikipedia.org/wiki/Bloom_filter

https://zh.wikipedia.org/zh-cn/布隆過濾器

https://llimllib.github.io/bloomfilter-tutorial

https://www.geeksforgeeks.org/bloom-filter-in-java-with-examples/

《數學之美》


題圖:wikipedia.org極客教程:996geek.com個人博客:binarylife.icu

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/370520.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/370520.shtml
英文地址,請注明出處:http://en.pswp.cn/news/370520.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

STM32上使用JSON

一、STM32工程中添加JSON 最近在一網2串項目&#xff0c;串口和網口之間可能需要定義一下簡單的通信協議&#xff0c;而通信協議上則需要去定義一下通信的數據格式&#xff0c;上次聽劍鋒說要用Json來定義&#xff0c;目前查了下資料具體如何去應用還不 會。因為最新的KEIL上支…

Flex 學習

Flex案例一&#xff1a; 1 <html>2 <head>3 <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> 4 <title>無標題</title>5 <style type"text/css">6 body,h1,h2,h3,h4,…

Cocos2d-X中實現自己定義菜單處理事件

當用戶點擊再松開后才會響應菜單事件&#xff0c;而在游戲中有些游戲須要玩家點擊后就處理事件。如玩坦克大戰的時候&#xff0c;玩家是點擊一下就發射子彈。并是點擊松手后發射子彈&#xff0c;在Cocos2d-X中沒有這樣的消息。以下就通過自己定義的方式實現當用戶點擊后就調用處…

java linkedhashset_java之LinkedHashSet

LinkedHashSet是Set集合的一個實現&#xff0c;具有set集合不重復的特點&#xff0c;同時具有可預測的迭代順序&#xff0c;也就是我們插入的順序。并且linkedHashSet是一個非線程安全的集合。如果有多個線程同時訪問當前linkedhashset集合容器&#xff0c;并且有一個線程對當前…

使用Spring Integration輪詢http端點

如果您想用Spring Integration編寫一個流程來輪詢HTTP端點并從http端點收集一些內容以進行進一步處理&#xff0c;那有點不直觀。 Spring Integration提供了幾種與HTTP端點集成的方式- Http出站適配器–將消息發送到http端點 Http出站網關–將消息發送到http端點并收集響應作…

python模塊離線安裝_離線安裝db2的python模塊ibm_db

1、為什么要離線安裝 沒網&#xff0c;在銀行工作&#xff0c;服務器環境配置&#xff0c;完全離線&#xff08;本來五分鐘搞定的事情&#xff0c;非要搞一天。我服&#xff01;&#xff01;&#xff09; 2、安裝步驟 視情況而定。 3。一個下載db2的client包&#xff0c;官網下…

Jmeter 場景設計

今天的業務場景是&#xff1a; 1.管理員登錄后臺---登錄成功后添加一個某類型的產品---產品添加成功后&#xff0c;再為該產品添加10個排期。 2.管理員登錄后臺--登錄成功后添加多個不同類型產品---產品全部添加完成后&#xff0c;依次為所有產品添加10個排期。 這是兩種不同的…

Android IPC機制(五)用Socket實現跨進程聊天程序

1.Socket簡介 Socket也稱作“套接字“&#xff0c;是在應用層和傳輸層之間的一個抽象層&#xff0c;它把TCP/IP層復雜的操作抽象為幾個簡單的接口供應用層調用以實現進程在網絡中通信。它分為流式套接字和數據包套接字&#xff0c;分別對應網絡傳輸控制層的TCP和UDP協議。TCP協…

ArcGIS 網絡分析[4] 網絡數據集深入淺出之連通性、網絡數據集的屬性及轉彎要素...

前面介紹完了如何創建網絡數據集、如何使用網絡分析功能&#xff0c;當然還有的讀者會迷惑于一些更深層次的問題&#xff0c;比如網絡數據集的連通性問題等。 因為不可能面面俱到&#xff0c;我只能挑重點來闡述&#xff0c;我覺得網絡數據集的連通性、屬性和轉彎是初學者中比較…

java獲取byte 長度_java獲取字節的長度.

我們經常要獲取中文,數字,或者英文字符所占字節的長度,下面就列出各種編碼格式下所占字節的長度:代碼如下:package pack.java.midea.dao;import java.io.UnsupportedEncodingException;/*** 測試;* author zhouhaitao* 2012-5-17*/public class Test {/*** param args* throws …

Batoo JPA –比領先的JPA提供商快15倍

介紹 我早在2000年代就喜歡JPA 1.0。 我甚至在穩定版本發布之前就將其與EJB 3.0一起使用。 我非常喜歡它&#xff0c;因此我為JBoss 3.x實現貢獻了一些零碎的部分。 那時我們公司規模還很小。 創建新功能和應用程序比性能更重要&#xff0c;因為我們有很多想法&#xff0c;我…

python軟件是哪個國家的品牌_有哪些好用的軟件被國人誤認為是外國研發的?

國產軟件被標榜上了英文&#xff0c;即便不是英文&#xff0c;用拼音寫出來&#xff0c;也會有人誤認為是國外的軟件。因為這樣可以顯得高大上&#xff0c;為什么我們會有這樣的想法&#xff0c;是崇洋媚外嗎&#xff0c;并不是&#xff0c;而是之前的國產軟件的確有不少讓我們…

簡單的Session案例 —— 一次性驗證碼

一次性驗證碼的主要目的就是為了限制人們利用工具軟件來暴力猜測密碼&#xff0c;其原理與利用Session防止表單重復提交的原理基本一樣&#xff0c;只是將表單標識號變成了驗證碼的形式&#xff0c;并且要求用戶將提示的驗證碼手工填寫進一個表單字段中&#xff0c;而不是通過表…

[BZOJ2064]分裂

[BZOJ2064]分裂 試題描述 背景&#xff1a; 和久必分&#xff0c;分久必和。。。 題目描述&#xff1a; 中國歷史上上分分和和次數非常多。。通讀中國歷史的WJMZBMR表示毫無壓力。 同時經常搞OI的他把這個變成了一個數學模型。 假設中國的國土總和是不變的。 每個國家都可以用他…

CSS3選擇器

基本選擇器 回顧選擇器 通配符選擇器元素選擇器類選擇器ID選擇器后代選擇器新增基本選擇器 子元素選擇器相鄰兄弟選擇器通用兄弟選擇器群組選擇器 子元素選擇器 概念&#xff1a;子元素選擇器只能選擇某元素的子元素 語法&#xff1a;父元素 > 子元素 &#xff08;Fathe…

eclipse java工程目錄_轉載:Eclipse下的java工程目錄

對新手來講&#xff0c;一個Java工程內部的多個文件夾經常會讓大家困惑。更可惡的是莫名其妙的路徑問題&#xff0c;在Eclipse編寫Java程序中&#xff0c;出現頻率最高的錯誤很可能就是路徑問題。這些問題原因其實都是一個&#xff0c;就是關于Java工程內的文件結構理解不清&am…

作為JBoss AS 7模塊運行Drools 5.4.0 Final

Drools 5引入了業務邏輯集成平臺&#xff0c;該平臺為規則&#xff0c;工作流和事件處理提供了統一的集成平臺。 它是從頭開始設計的&#xff0c;因此每個方面都是一流的公民&#xff0c;毫不妥協。 Drools 5已分為4個主要子項目&#xff1a; Drools Guvnor&#xff08;BRMS …

postgres 支持的線程數_線程池被打滿了怎么處理呢,你是否真的了解線程池?

0、前言線程池&#xff0c;顧名思義就是線程的池子&#xff0c;在每次需要取線程去執行任務的時候&#xff0c;沒必要每次都創建新線程執行&#xff0c;線程池就是起著維護線程的作用&#xff0c;當有任務的時候就取出一個線程執行&#xff0c;如果任務執行完成則把線程放回到池…

[樹形DP]沒有上司的舞會

題目鏈接 思考 首先本題中的關系是一種樹形結構&#xff0c;而且符號最優子結構和無后效性&#xff0c;所以可以進行記憶化搜索。 那么首先要在這顆樹中選出一個點作為根節點&#xff0c;按照習慣我們將沒有父節點的點作為根節點。 接下來要思考的是 狀態&#xff1a; dp[i][0…

網頁自適應

1.viewport標簽 基本語法&#xff1a; <meta name”viewport” content”widthdevice-width,initial-scale1” /> 上面這行代碼的意思是&#xff0c;面積的100%&#xff0c;網頁寬度默認等于屏幕寬度&#xff08;widthdevice-width&#xff09;, 原始縮放比例&#x…