布隆過濾器BloomFilter

BloomFilter原理圖

x,y,zx,y,z經由哈希函數映射將各自在Bitmap中的3個位置置爲1,當ww出現時,僅當3個標誌位都爲1時,才表示ww在集合中。圖中所示的狀況,布隆過濾器將斷定w不在集合中。

算法比較複雜,也不是本文研究的範疇,直接使用已有的實現。java

google的guava包中提供了BloomFilter類,咱們直接使用它來進行一下簡單的測試。 新建一個maven工程,引入guava包(建議你們使用這個包,裏面有不少google封裝好的代碼);算法

<dependencies>  
    <dependency>  
        <groupId>com.google.guava</groupId>  
        <artifactId>guava</artifactId>  
        <version>22.0</version>  
    </dependency>  
</dependencies> 
複製代碼

測試

  • 往過濾器裏放一百萬個數,而後去驗證這一百萬個數是否能經過過濾器,目的是校驗是壞人是否必定被抓。
  • 另找1萬個不在這一百萬範圍內的數,去驗證漏網之魚的機率,也就是布隆過濾器的誤傷狀況。
import com.google.common.hash.BloomFilter;  
import com.google.common.hash.Funnels;  
  
import java.util.ArrayList;  
import java.util.List;  

public class Test {  
    private static int size = 1000000;  
  
    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size);  
  
    public static void main(String[] args) {  
        for (int i = 0; i < size; i++) {  
            bloomFilter.put(i);  
        }  
  
        for (int i = 0; i < size; i++) {  
            if (!bloomFilter.mightContain(i)) {  
                System.out.println("有壞人逃脫了");  
            }  
        }  
  
        List<Integer> list = new ArrayList<Integer>(1000);  
        for (int i = size + 10000; i < size + 20000; i++) {  
            if (bloomFilter.mightContain(i)) {  
                list.add(i);  
            }  
        }  
        System.out.println("有誤傷的數量:" + list.size());  
    }  
}  
複製代碼

運行後發現,沒有壞人逃脫,當咱們去遍歷這一百萬個數時,他們都在過濾器內被識別了出來。數組

誤傷的數量是330.也就是有330個不在過濾器內的值,被認爲在過濾器裏,被誤傷了。錯誤機率是3%做用,爲啥是3%呢。bash

跟蹤源碼

在create的多個重載方法中,最終走的是有4個參數的那個。咱們上面用的是有2個參數的,注意看圖片最下面,咱們不填第三方參數時,默認補了一個0.03,這個就表明了容許的錯誤機率是3%。第四個參數是哈希算法,默認是BloomFilterStrategies.MURMUR128_MITZ_64。maven

在第127行能夠看到,要存下這一百萬個數,位數組的大小是7298440,700多萬位,實際上要完整存下100萬個數,一個int是4字節32位,咱們須要4X8X1000000=3千2百萬位,差很少只用了1/5的容量,若是是HashMap,按HashMap 50%的存儲效率,咱們須要6千4百萬位,全部布隆過濾器佔用空間很小,只有HashMap的1/10-1/5做用。函數

128行是hash函數的數量,是5,也就是說系統以爲要保證3%的錯誤率,須要5個函數外加700多萬位便可。用3%偏差換十分之一的內存佔用。測試

咱們也能夠修改這個錯誤機率,譬如咱們改成0.0001萬分之一。google

private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.0001);  
複製代碼

二次運行

咱們將28行改成10萬個數,發現結果爲「誤傷12」。能夠看到這個機率是比較靠譜的。 當機率爲萬分之一時,咱們看看空間佔用。

此時bit容量已經從700多萬到1900萬了,函數數量也從5變成了13;機率從3%縮減到萬分之一;

以上是布隆過濾器的簡單使用。具體的應用場景,具體實現。spa

相關文章
相關標籤/搜索