布隆過濾器(Bloom Filter) 是由 Howard Bloom在1970年提出的二進制向量數據結構
,它具備很好的空間和時間效率
,被用來檢測一個元素是否是集合中的一個成員
,即斷定 「可能已存在和絕對不存在」
兩種狀況。若是檢測結果爲是,該元素不必定在集合中;但若是檢測結果爲否,該元素必定不在集合中,所以Bloom filter具備100%的召回率
。git
布隆過濾器的核心是一個超大的位數組
和幾個哈希函數
。假設位數組的長度爲m,哈希函數的個數爲k。
下圖表示有三個hash函數,好比一個集合中有x,y,z三個元素,分別用三個hash函數映射到二進制序列的某些位上,假設咱們判斷w是否在集合中,一樣用三個hash函數來映射,結果發現取得的結果不全爲1,則表示w不在集合裏面。github
工做流程:數組
一、優勢:緩存
空間和時間效率
存儲空間和插入/查詢時間都是常數
。全集
,其它任何數據結構都不能。二、缺點:數據結構
誤判率會隨元素的增長而增長
不能從布隆過濾器中刪除元素
布隆過濾器思路比較簡單,可是對於布隆過濾器的隨機映射函數設計,須要計算幾回,向量長度設置爲多少比較合適,這個纔是須要認真討論的。
若是向量長度過短,會致使誤判率直線上升。
若是向量太長,會浪費大量內存。
若是計算次數過多,會佔用計算資源,且很容易很快就把過濾器填滿。app
1. 開源包簡單演示函數
package main import ( "fmt" "github.com/willf/bitset" "math/rand" ) func main() { Foo() bar() } func Foo() { var b bitset.BitSet // 定義一個BitSet對象 b.Set(1).Set(2).Set(3) //添加3個元素 if b.Test(2) { fmt.Println("2已經存在") } fmt.Println("總數:", b.Count()) b.Clear(2) if !b.Test(2) { fmt.Println("2不存在") } fmt.Println("總數:", b.Count()) } func bar() { fmt.Printf("Hello from BitSet!\n") var b bitset.BitSet // play some Go Fish for i := 0; i < 100; i++ { card1 := uint(rand.Intn(52)) card2 := uint(rand.Intn(52)) b.Set(card1) if b.Test(card2) { fmt.Println("Go Fish!") } b.Clear(card1) } // Chaining b.Set(10).Set(11) for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) { fmt.Println("The following bit is set:", i) } // 交集 if b.Intersection(bitset.New(100).Set(10)).Count() == 1 { fmt.Println("Intersection works.") } else { fmt.Println("Intersection doesn't work???") } }
2. 封裝的方法:測試
//---------------------------------------------------------------------------- // @ Copyright (C) free license,without warranty of any kind . // @ Author: hollson <hollson@live.com> // @ Date: 2019-12-06 // @ Version: 1.0.0 //------------------------------------------------------------------------------ package bloomx import "github.com/willf/bitset" const DEFAULT_SIZE = 2<<24 var seeds = []uint{7, 11, 13, 31, 37, 61} type BloomFilter struct { Set *bitset.BitSet Funcs [6]SimpleHash } func NewBloomFilter() *BloomFilter { bf := new(BloomFilter) for i:=0;i< len(bf.Funcs);i++{ bf.Funcs[i] = SimpleHash{DEFAULT_SIZE,seeds[i]} } bf.Set = bitset.New(DEFAULT_SIZE) return bf } func (bf BloomFilter) Add(value string){ for _,f:=range(bf.Funcs){ bf.Set.Set(f.hash(value)) } } func (bf BloomFilter) Contains(value string) bool { if value == "" { return false } ret := true for _,f:=range(bf.Funcs){ ret = ret && bf.Set.Test(f.hash(value)) } return ret } type SimpleHash struct{ Cap uint Seed uint } func (s SimpleHash) hash(value string) uint{ var result uint = 0 for i:=0;i< len(value);i++{ result = result*s.Seed+uint(value[i]) } return (s.Cap-1)&result }
func main() { filter := bloomx.NewBloomFilter() fmt.Println(filter.Funcs[1].Seed) str1 := "hello,bloom filter!" filter.Add(str1) str2 := "A happy day" filter.Add(str2) str3 := "Greate wall" filter.Add(str3) fmt.Println(filter.Set.Count()) fmt.Println(filter.Contains(str1)) fmt.Println(filter.Contains(str2)) fmt.Println(filter.Contains(str3)) fmt.Println(filter.Contains("blockchain technology")) }
100W數量級下布隆過濾器測試,源碼可參考https://download.csdn.net/download/Gusand/12018239ui
參考: 推薦:https://www.cnblogs.com/z941030/p/9218356.html https://www.jianshu.com/p/01309d298a0e https://www.cnblogs.com/zengdan-develpoer/p/4425167.html https://blog.csdn.net/liuzhijun301/article/details/83040178 https://github.com/willf/bloom