最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis?BloomFilter布隆過濾器原理與實現(xiàn)

 更新時間:2022年10月11日 09:25:19   作者:~龐貝  
你在開發(fā)或者面試過程中,有沒有遇到過?海量數(shù)據(jù)需要查重,緩存穿透怎么避免等等這樣的問題呢?下面這個東西超棒,好好了解下,面試過關斬將,凸顯你的不一樣

Bloom Filter 概念

布隆過濾器(英語:Bloom Filter)是1970年由一個叫布隆的小伙子提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數(shù)。布隆過濾器可以用于檢索一個元素是否在一個集合中。它的優(yōu)點是空間效率和查詢時間都遠遠超過一般的算法,缺點是有一定的誤識別率和刪除困難。

Bloom Filter 原理

布隆過濾器的原理是,當一個元素被加入集合時,通過K個散列函數(shù)將這個元素映射成一個位數(shù)組中的K個點,把它們置為1。檢索時,我們只要看看這些點是不是都是1就(大約)知道集合中有沒有它了:如果這些點有任何一個0,則被檢元素一定不在;如果都是1,則被檢元素很可能在。這就是布隆過濾器的基本思想。

Bloom Filter跟單哈希函數(shù)Bit-Map不同之處在于:Bloom Filter使用了k個哈希函數(shù),每個字符串跟k個bit對應。從而降低了沖突的概率

緩存穿透

每次查詢都會直接打到DB

簡而言之,言而簡之就是我們先把我們數(shù)據(jù)庫的數(shù)據(jù)都加載到我們的過濾器中,比如數(shù)據(jù)庫的id現(xiàn)在有:1、2、3

那就用id:1 為例子他在上圖中經(jīng)過三次hash之后,把三次原本值0的地方改為1

下次數(shù)據(jù)進來查詢的時候如果id的值是1,那么我就把1拿去三次hash 發(fā)現(xiàn)三次hash的值,跟上面的三個位置完全一樣,那就能證明過濾器中有1的

反之如果不一樣就說明不存在了

那應用的場景在哪里呢?一般我們都會用來防止緩存擊穿

簡單來說就是你數(shù)據(jù)庫的id都是1開始然后自增的,那我知道你接口是通過id查詢的,我就拿負數(shù)去查詢,這個時候,會發(fā)現(xiàn)緩存里面沒這個數(shù)據(jù),我又去數(shù)據(jù)庫查也沒有,一個請求這樣,100個,1000個,10000個呢?你的DB基本上就扛不住了,如果在緩存里面加上這個,是不是就不存在了,你判斷沒這個數(shù)據(jù)就不去查了,直接return一個數(shù)據(jù)為空不就好了嘛。

這玩意這么好使那有啥缺點么?有的,我們接著往下看

Bloom Filter的缺點

bloom filter之所以能做到在時間和空間上的效率比較高,是因為犧牲了判斷的準確率、刪除的便利性

存在誤判,可能要查到的元素并沒有在容器中,但是hash之后得到的k個位置上值都是1。如果bloom filter中存儲的是黑名單,那么可以通過建立一個白名單來存儲可能會誤判的元素。

刪除困難。一個放入容器的元素映射到bit數(shù)組的k個位置上是1,刪除的時候不能簡單的直接置為0,可能會影響其他元素的判斷??梢圆捎?a href="http://m.fzitv.net/article/264689.htm" target="_blank">Counting Bloom Filter

常見問題

1、為何要使用多個哈希函數(shù)?

Hash本身就會面臨沖突,如果只使用一個哈希函數(shù),那么沖突的概率會比較高。例如長度100的數(shù)組,如果只使用一個哈希函數(shù),添加一個元素后,添加第二個元素時沖突的概率為1%,添加第三個元素時沖突的概率為2%…但如果使用兩個哈希函數(shù),添加一個元素后,添加第二個元素時沖突的概率降為萬分之4(四種可能的沖突情況,情況總數(shù)100x100)

go語言實現(xiàn)

package main
import (
	"fmt"
	"github.com/bits-and-blooms/bitset"
)
//設置哈希數(shù)組默認大小為16
const DefaultSize = 16
//設置種子,保證不同哈希函數(shù)有不同的計算方式
var seeds = []uint{7, 11, 13, 31, 37, 61}
//布隆過濾器結構,包括二進制數(shù)組和多個哈希函數(shù)
type BloomFilter struct {
	//使用第三方庫
	set *bitset.BitSet
	//指定長度為6
	hashFuncs [6]func(seed uint, value string) uint
}
//構造一個布隆過濾器,包括數(shù)組和哈希函數(shù)的初始化
func NewBloomFilter() *BloomFilter {
	bf := new(BloomFilter)
	bf.set = bitset.New(DefaultSize)

	for i := 0; i < len(bf.hashFuncs); i++ {
		bf.hashFuncs[i] = createHash()
	}
	return bf
}
//構造6個哈希函數(shù),每個哈希函數(shù)有參數(shù)seed保證計算方式的不同
func createHash() func(seed uint, value string) uint {
	return func(seed uint, value string) uint {
		var result uint = 0
		for i := 0; i < len(value); i++ {
			result = result*seed + uint(value[i])
		}
		//length = 2^n 時,X % length = X & (length - 1)
		return result & (DefaultSize - 1)
	}
}
//添加元素
func (b *BloomFilter) add(value string) {
	for i, f := range b.hashFuncs {
		//將哈希函數(shù)計算結果對應的數(shù)組位置1
		b.set.Set(f(seeds[i], value))
	}
}
//判斷元素是否存在
func (b *BloomFilter) contains(value string) bool {
	//調(diào)用每個哈希函數(shù),并且判斷數(shù)組對應位是否為1
	//如果不為1,直接返回false,表明一定不存在
	for i, f := range b.hashFuncs {
		//result = result && b.set.Test(f(seeds[i], value))
		if !b.set.Test(f(seeds[i], value)) {
			return false
		}
	}
	return true
}
func main() {
	filter := NewBloomFilter()
	filter.add("asd")
	fmt.Println(filter.contains("asd"))
	fmt.Println(filter.contains("2222"))
	fmt.Println(filter.contains("155343"))
}

輸出結果如下:

true
false
false

到此這篇關于Redis BloomFilter布隆過濾器原理與實現(xiàn)的文章就介紹到這了,更多相關Redis BloomFilter內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • golang如何用http.NewRequest創(chuàng)建get和post請求

    golang如何用http.NewRequest創(chuàng)建get和post請求

    這篇文章主要介紹了golang如何用http.NewRequest創(chuàng)建get和post請求問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Go語言文件讀取的一些總結

    Go語言文件讀取的一些總結

    這篇文章主要介紹了Go語言文件讀取的一些總結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • golang中的單引號轉義問題

    golang中的單引號轉義問題

    這篇文章主要介紹了golang中的單引號轉義問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Golang字符串的拼接方法匯總

    Golang字符串的拼接方法匯總

    字符串拼接在日常開發(fā)中是很常見的需求,今天我們來探討下如何用golang來實現(xiàn)字符串的拼接
    2018-10-10
  • Golang請求fasthttp實踐

    Golang請求fasthttp實踐

    本文主要介紹了Golang請求fasthttp實踐,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • golang 常用定時任務匯總

    golang 常用定時任務匯總

    這篇文章主要介紹了golang 常用定時任務匯總,golang利用goroutine外加github.com/gorhill/cronexpr庫就可實現(xiàn)定時任務,具體代碼介紹,需要的小伙伴可以參考一下
    2022-09-09
  • GoLang抽獎系統(tǒng)簡易實現(xiàn)流程

    GoLang抽獎系統(tǒng)簡易實現(xiàn)流程

    這篇文章主要介紹了GoLang抽獎系統(tǒng)實現(xiàn)流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-12-12
  • Go語言讀取,設置Cookie及設置cookie過期方法詳解

    Go語言讀取,設置Cookie及設置cookie過期方法詳解

    這篇文章主要介紹了Go語言讀取,設置Cookie及設置cookie過期方法詳解,需要的朋友可以參考下
    2022-04-04
  • 一文詳解Golang的函數(shù)特性

    一文詳解Golang的函數(shù)特性

    函數(shù)是?Golang?中非常重要的組成部分之一,它們提供了代碼的可重用性和組織性。在本文中,我們將深入了解?Golang?函數(shù)的多個方面,希望對大家有所幫助
    2023-04-04
  • Go語言中日志統(tǒng)一處理詳解

    Go語言中日志統(tǒng)一處理詳解

    在現(xiàn)代軟件開發(fā)中,日志記錄是一項至關重要的任務,它不僅幫助開發(fā)人員診斷問題,還有助于監(jiān)控和維護應用程序,本文主要來和大家聊聊日志的統(tǒng)一處理,感興趣的小伙伴可以了解下
    2024-01-01

最新評論

靖远县| 阳曲县| 汶上县| 军事| 高阳县| 彰化县| 油尖旺区| 长寿区| 洪洞县| 南漳县| 千阳县| 宣威市| 北票市| 湖州市| 屏山县| 岳普湖县| 红河县| 柏乡县| 邮箱| 凤山市| 洪江市| 平阴县| 湖南省| 衡山县| 乳山市| 宿松县| 平山县| 康乐县| 芜湖市| 乾安县| 墨江| 乌鲁木齐县| 宿州市| 宁城县| 黎平县| 吴忠市| 德格县| 时尚| 嘉黎县| 大丰市| 独山县|