Golang中的布隆過濾器

1. 布隆過濾器的概念

布隆過濾器(Bloom Filter) 是由 Howard Bloom在1970年提出的二進制向量數據結構,它具備很好的空間和時間效率,被用來檢測一個元素是否是集合中的一個成員,即斷定 「可能已存在和絕對不存在」 兩種狀況。若是檢測結果爲是,該元素不必定在集合中;但若是檢測結果爲否,該元素必定不在集合中,所以Bloom filter具備100%的召回率git


2. 布隆過濾器應用場景

  • 垃圾郵件過濾
  • 防止緩存擊穿
  • 比特幣交易查詢
  • 爬蟲的URL過濾
  • IP黑名單
  • 查詢加速【好比基於KV結構的數據】
  • 集合元素重複的判斷


3. 布隆過濾器工做原理

布隆過濾器的核心是一個超大的位數組幾個哈希函數。假設位數組的長度爲m,哈希函數的個數爲k。
下圖表示有三個hash函數,好比一個集合中有x,y,z三個元素,分別用三個hash函數映射到二進制序列的某些位上,假設咱們判斷w是否在集合中,一樣用三個hash函數來映射,結果發現取得的結果不全爲1,則表示w不在集合裏面。github

在這裏插入圖片描述

工做流程:數組

  • 第一步:開闢空間:
    開闢一個長度爲m的位數組(或者稱二進制向量),這個不一樣的語言有不一樣的實現方式,甚至你能夠用文件來實現。
  • 第二步:尋找hash函數
    獲取幾個hash函數,前輩們已經發明瞭不少運行良好的hash函數,好比BKDRHash,JSHash,RSHash等等。這些hash函數咱們直接獲取就能夠了。
  • 第三步:寫入數據
    將所須要判斷的內容通過這些hash函數計算,獲得幾個值,好比用3個hash函數,獲得值分別是1000,2000,3000。以後設置m位數組的第1000,2000,3000位的值位二進制1。
  • 第四步:判斷
    接下來就能夠判斷一個新的內容是否是在咱們的集合中。判斷的流程和寫入的流程是一致的。


4. 布隆過濾器的優缺點

一、優勢:緩存

  • 有很好的空間和時間效率
  • 存儲空間和插入/查詢時間都是常數
  • Hash函數相互之間沒有關係,方便由硬件並行實現。
  • 不須要存儲元素自己,在某些對保密要求很是嚴格的場合有優點。
  • 布隆過濾器能夠表示全集,其它任何數據結構都不能。

二、缺點:數據結構

  • 誤判率會隨元素的增長而增長
  • 不能從布隆過濾器中刪除元素


5. 布隆過濾器注意事項

布隆過濾器思路比較簡單,可是對於布隆過濾器的隨機映射函數設計,須要計算幾回,向量長度設置爲多少比較合適,這個纔是須要認真討論的。
若是向量長度過短,會致使誤判率直線上升。
若是向量太長,會浪費大量內存。
若是計算次數過多,會佔用計算資源,且很容易很快就把過濾器填滿。app


6. Go實現布隆過濾器

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

相關文章
相關標籤/搜索