1. 程式人生 > >過濾器系列(一)—— Bloom filter

過濾器系列(一)—— Bloom filter

因為要做過濾器相關內容,最近讀了一些過濾器方面的文章,準備從中提取主要思想寫幾篇部落格。

作為這系列的第一篇文章,首先得講一下過濾器是幹什麼用的。從歷史發展來看,過濾器最早出現是作為散列表的替代品,那麼功能就要和散列表差不多,主要是查詢當前的元素是否在我已知的集合裡。但是隨著資料量不斷增大,散列表相對來說佔用空間過大,而空間佔用小的查詢樹的\(O(logn)\)時間複雜度又太高。於是有人想出來能否用正確率做代價,換取較高的查詢速度和較小的儲存佔用,這就是過濾器。當然,這裡所允許的錯誤僅限假陽性,例如我們做一個關於代理ip地址的過濾器,當有一個不是代理的ip地址發來,我們也許會把它錯認成是代理ip,但是我們不會允許一個代理ip被錯認成非代理ip,簡單的說,就是寧可錯殺,不可放過。

作為第一篇,按照歷史角度,先說布隆過濾器(bloom filter)。原版的布隆過濾器很樸素,只支援插入和查詢兩個操作,下面我們看它的原理。

首先,布隆過濾器申請了一片空間,存了一個數組,每個元素都只有1個bit,共有N個元素,初始化每個值都為0。如下圖所示。(實際並沒有index這一行,僅僅是為了方便觀看)
image1

插入操作

下一步就是如何插入資料。布隆過濾器要求你事先定義K個Hash函式,這K個Hash函式都是從定義域對映到上圖中的index空間(即N)。通過這K個Hash函式,我們對一條新的資料x,計算出\(h_0(x),h_1(x),....h_{k-1}(x)\),這樣就得到了K個地址。我們將這K個地址的位元位置1.這裡就有值得注意的地方,因為我們的過濾器的大小遠遠小於資料集大小,那麼常常會有Hash之後對映到同一個位置的資料,不要擔心,照常置1。

下面的例子是K=3,\(h_0(x)=2,h_1(x)=5,h_2(x)=7\)。如圖所示
image2

查詢操作

當插入其他一些資料後,過濾器可能變成下圖所示,我們不關心中間經歷了什麼。

image3
我們現在查詢剛才第一次插入的資料是否在過濾器中,那麼同樣計算\(h_0(x),h_1(x),h_2(x)\),算出3個地址,2,5,7,去表中查詢,若3個地址的資料都為1,則判斷在過濾器中,否則判斷不在過濾器中。

演算法和資料結構都很簡單,我們下面說的是對布隆過濾器的一些分析和題外話,有興趣的讀者可以繼續閱讀。

我們在過濾器上很關注三個指標,一個是操作的時間複雜度,一個是平均每條資料佔用的位元數,最後是錯誤率。下面我們分析一下。

時間複雜度

布隆過濾器上的兩個操作,插入和查詢,都只是計算一下K個Hash函式的值,然後進行K次訪存操作。那麼時間上很明顯是\(O(K)\),其實不算也知道,一個替代Hash表的過濾器,操作代價必須是常數級別。

平均每條資料佔用的位元數 and 錯誤率

直覺上,很容易得出這兩個衡量指標其實是矛盾的,當想要較低錯誤率時就要增大空間;想要減小佔用空間時,那麼由於Hash碰撞的次數變多,錯誤率也會提高。我們在這裡將錯誤率作為已知來計算平均每條資料佔用的位元數。為什麼這麼做?因為在實際應用中我們可以對過濾器設定一個錯誤率作為標準,通常情況下我們對這一點要求更嚴格。

我們設陣列總大小為\(N\),插入n條資料後表中還為0的資料佔全部的比例為\(\phi\)。那麼

\(\phi = (1-K / N)^n\)-------------------------(1)
讀者可以想想為什麼不是\(K * n / N\),在這裡,我們其實省略了Hash函式預設是隨機分佈到全空間的。

設錯誤率為\(P\)

\(P = (1-\phi)^K\) ----------------------------(2)
錯誤只發生隨機分佈到K個地址,結果在K個地址都有資料用了,那麼不管你是否在過濾器中,布隆過濾器都會判斷你在其中,這就是錯誤來源。

然後我們對(1)式兩邊取對數

\(log_2^\phi = log_2^{(1-K/N)^n}\)
使用換底公式
\(log_2^\phi = log_2^{(1-K/N)^n} = log_e^{(1-d/N)^n} * log_2^e = -n * K / N *log_2^e\) ---(3)

我們要求的平均每條資料佔用的位元數\(N(bit) / n = log_2^{1/P} * log_2^e / (log_2^\phi * log_2^{(1-\phi)})\),通過極值點計算可以得到分母最大時,\(\phi=0.5\),分母為1,則結果為\(N/n = log_2^{1/P} / ln2\)

可以看到,每條資料佔用的位元數與錯誤率的對數成反比。

之後我會先把幾個不同思想的過濾器介紹一遍,最後會有關於布隆過濾器的一些變形

相關推薦

過濾器系列—— Bloom filter

因為要做過濾器相關內容,最近讀了一些過濾器方面的文章,準備從中提取主要思想寫幾篇部落格。 作為這系列的第一篇文章,首先得講一下過濾器是幹什麼用的。從歷史發展來看,過濾器最早出現是作為散列表的替代品,那麼功能就要和散列表差不多,主要是查詢當前的元素是否在我已知的集合裡。但是隨著資料量不斷增大,散列表相對來說佔用

Blockchain的魚和熊掌系列7Bloom Filter續SPV

Bloom Filter, a space-efficient randomized data structure, is mainly designed for many portable devices with limited storage space.

過濾器系列—— Cuckoo filter

這一篇講的是布穀過濾器(cuckoo fliter),這個名字來源於更早發表的布穀雜湊(cuckoo hash),儘管我也不知道為什麼當初要給這種散列表起個鳥名=_= 由於布穀過濾器本身的思想就源自於布穀雜湊,那麼我們就從布穀雜湊開始說它的設計思想。產生布谷散列表的一個重要背景是人們對於球盒問題的分析:給定N

【ABAP自學系列

發的 img api .cn ima code pat 查看 屏幕 一、查看補丁包級別 然後看Patch Level即可。 常用T-code: SE38(寫程序) SE80(屏幕開發) Smartform(開發smartform打印) SE37(可以查看function

Linux基礎學習系列

內核版本 比較 其中 問題 測試版 工具 含義 語言 復制   Linux是一種類似於UNIX的操作系統,由Linus Torvalds於1991年在minix操作系統的基礎創建。Linux憑借其優良特性已經成為目前發展潛力最大的操作系統。   Linux的版本有內核版本和

spring boot學習系列

web服務器 應用程序 spring 控制器 做什麽 spring boot開發第一個應用程序1、spring boot是什麽?2、spring boot容易上手嗎?寫這篇文章技術文章,主要是記錄日常的學習以及理解。我們重新認識一下spring假設你受命使用spring開發一個簡單的hel

asp.net core入門教程系列

home padding 方式 title sys 活性 elf tro ash Asp.Net Core簡介 ASP.NET Core 是一個全新的開源、跨平臺框架,可以用它來構建基於網絡連接的現代雲應用程序,比如:Web 應用,IoT(Internet Of Thin

【原創】源碼角度分析Android的消息機制系列——Android消息機制概述

run 權限 開發 等待 通過 讀取 概述 走了 color ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 1.為什麽需要Android的消息機制 因為Android系統不允許在子線程中去訪問UI,即Android系統不允許在子線程中更新UI。 為什麽不允許

vue系列子組件和父組件

top parent sage too msg pro 工具 light java 父組件傳遞數據到子組件props 父組件 <template> <div class="main"> <div class="top">

Hadoop源碼系列FairScheduler申請和分配container的過程

opened running fetch utils ostream png on() threshold metadata 1、如何申請資源 1.1 如何啟動AM並申請資源 1.1.1 如何啟動AM val yarnClient = YarnClient.createY

源碼分析系列x264_main_dataflow

images 9.png 所有 malloc 控制 相關 .com 圖1 memory http://www.cnblogs.com/xkfz007/articles/2616153.html 幀內幀間編碼部分關鍵函數 1.1 x264_encoder_open (x

ORM框架疏理——廖雪峰實戰系列

命令 delete ica 隱式 orm mod prim 數據結構 lam ORM(Object Relational Mapping,對象關系映射),是一種程序設計技術,用於實現面向對象編程語言裏不同類型系統的數據之間的轉換。從效果上來說,它其實創建了一個可在編程語言裏

優秀開源軟件學習系列——從零學習Spring4以及學習方法分享

文檔 軟件 準備 相關性 培訓 獎勵 在哪裏 方式 列表 一、目的1.掌握Spring4怎樣使用,以便將這個框架作為自己的一項技能。2.掌握Spring官網是怎樣介紹其產品的,在心中對Spring有最官方的、最直觀的了解。在Spring的相關領域,能夠知道怎麽下載Sprin

PHP系列PHP流程控制結構

php流程控制while(){}do{}while(); for( 表達式1; 表達式2;表達式3 ){ 語句或語句序列;} if(){}if(){}elseif{}<?php$i=0;while(true){ if($i>=100) break; echo "@@

RabbitMQ學習系列: 介紹

ref 原理 二維碼 host 屬性 訂閱 什麽 設計 發的 1. 介紹   RabbitMQ是一個由erlang開發的基於AMQP(Advanced Message Queue )協議的開源實現。用於在分布式系統中存儲轉發消息,在易用性、擴展性、高可用性等方面都非

Python開發MapReduce系列WordCount Demo

logs 3-9 line counter ota python開發 home num brush  原創,轉發請註明出處。   MapReduce是hadoop這只大象的核心,Hadoop 中,數據處理核心就是 MapReduce 程序設計模型。一個Map/Reduc

Javascript系列語法、關鍵保留字、變量

javascript ECMA是European Computer Manufacturers Association的縮寫,即歐洲計算機制造商協會。歐洲計算機制造商協會是制定信息傳輸與通訊的國際化標準組織。ECMAScript是ECMA制定的標準化腳本語言。目前JavaScript使用的ECMAS

Java集合幹貨系列-ArrayList源碼解析

div imp ins bject 增加 toa tof capacity == 前言 今天來介紹下ArrayList,在集合框架整體框架一章中,我們介紹了List接口,ArrayList繼承了AbstractList,實現了List。ArrayList在工作中經常用到,所

Openlayers系列關於地圖投影的理解

數據庫 nbsp 簡單的 是個 ace 投影 存儲 mongodb uid 近期開發以MongoDB為基礎的分布式地理數據管理平臺系統,被要求做一個簡單的demo給客戶進行演示。於是筆者便打算向數據庫中存儲一部分瓦片數據,寫一個簡單的存取服務器,使用Openlayers客戶

Python操作rabbitmq系列

targe 紅色 入門 web 之間 cap ssa 隊列 技術 從本文開始,接下來的內容,我們將討論rabbitmq的相關功能。我的這些文章,最終是要實現一個項目(具體是什麽暫不透露)。前面每一篇,都是在為這個系統做準備。rabbitmq,是我們這個項目的關鍵部分之一。所