Golang中的布隆過濾器

来源:https://www.cnblogs.com/Hollson/archive/2019/12/12/12031692.html
-Advertisement-
Play Games

[toc] 1. 布隆過濾器的概念 布隆過濾器(Bloom Filter) 是由 Howard Bloom在1970年提出的 ,它具有很好的 ,被用來 ,即判定 兩種情況。如果檢測結果為是,該元素不一定在集合中;但如果檢測結果為否,該元素一定不在集合中,因此Bloom filter 。 2. 布隆過 ...


目錄

1. 布隆過濾器的概念

布隆過濾器(Bloom Filter) 是由 Howard Bloom在1970年提出的二進位向量數據結構,它具有很好的空間和時間效率,被用來檢測一個元素是不是集合中的一個成員,即判定 “可能已存在和絕對不存在” 兩種情況。如果檢測結果為是,該元素不一定在集合中;但如果檢測結果為否,該元素一定不在集合中,因此Bloom filter具有100%的召回率


2. 布隆過濾器應用場景

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


3. 布隆過濾器工作原理

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

在這裡插入圖片描述

工作流程:

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


4. 布隆過濾器的優缺點

1、優點:

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

2、缺點:

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


5. 布隆過濾器註意事項

布隆過濾器思路比較簡單,但是對於布隆過濾器的隨機映射函數設計,需要計算幾次,向量長度設置為多少比較合適,這個才是需要認真討論的。
如果向量長度太短,會導致誤判率直線上升。
如果向量太長,會浪費大量記憶體。
如果計算次數過多,會占用計算資源,且很容易很快就把過濾器填滿。


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 <[email protected]>
// @ 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/12018239


參考:
推薦: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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 異常在我們的平時開發過程中是非常尋常並且經常會面對的,我們有很多方式來處理和使用異常。充分發揮異常的優點可以提高程式的可讀性,可靠性和可維護性。但是如果使用不當,也會帶來很多負面影響。 參考 effective java 第三版中對於異常的一些優秀實踐來做一下總結: No.1 只針對異常的情況才使用 ...
  • 類的基本特性內 approved 已批准 implemented 已實施 mandatory 強制性的 proposed 偍儀的 validated 已驗證 ...
  • 一、添加郵件頭,抄送等信息 1.mail["From"]表示發送者信息,包括姓名和郵件 2.mail["To"]表示接收者信息,包括姓名和郵件地址 3.mail["Subject"]表示摘要或者主題信息 from email.mime.text import MIMEText from email. ...
  • 山有山的高度,水有水的深度。人生就是一場修行,註定會經歷千迴百轉,方能遇到一生的摯愛,註定要經歷浮浮沉沉,才能領會生命的涵義。燃一盞心燈,照亮每一個黑暗的角落,微笑,是最美的詩行。 ...
  • 網上很多文章都推薦使用Ant下載編譯,但本地實踐中屢屢失敗,無法下載。 後來參考 https://blog.csdn.net/xiongyouqiang/article/details/78941077 總算把調試環境搭建完成。 以下文章幾乎完全copy上述網址,但稍作延展。 下載源碼 官網直接下載 ...
  • 事情的經過是這樣的: 又是奶茶,行吧行吧。 快點開工,爭取李大偉回來之前搞定。 李大偉說是6位數字密碼 那麼我們可以利用python生成全部的六位數字密碼 這樣,我們就生成了一個從000000到99999的密碼表。 並把它們存入到 passdict.txt 的文件中。 6位的密碼表就這麼大!!! 下 ...
  • Generate name based md5 UUID (version 3) 函數來源:fzaninotto/faker 地址:https://github.com/fzaninotto/Faker ...
  • 本文主要學習瞭如何在Eclipse里使用Tomcat伺服器。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...