日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

mysql开启布隆过滤器_海量数据去重之布隆过滤器

發(fā)布時(shí)間:2023/12/10 数据库 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql开启布隆过滤器_海量数据去重之布隆过滤器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

背景

在使?word?檔時(shí),word如何判斷某個(gè)單詞是否拼寫正確?

?絡(luò)爬?程序,怎么讓它不去爬相同的url???

垃圾郵件(短信)過(guò)濾算法如何設(shè)計(jì)?

公安辦案時(shí),如何判斷某嫌疑?是否在?逃名單中?

緩存穿透問(wèn)題如何解決?

先來(lái)看一個(gè)場(chǎng)景,假如我們的數(shù)據(jù)庫(kù)使用的是 mysql,緩存使用 redis。

server

redis

mysql

數(shù)據(jù)讀取步驟是這樣的:

先訪問(wèn) redis ,如果數(shù)據(jù)存在直接返回;如果不存在則進(jìn)行步驟 2;

訪問(wèn) mysql ,如果數(shù)據(jù)不存在,直接返回;如果存在則進(jìn)行步驟 3;

將 mysql 中存在的 key 寫回 redis;

出現(xiàn)的問(wèn)題: 如果 redis 和 mysql 中都沒(méi)有相應(yīng)的數(shù)據(jù),此時(shí)又有大量的該數(shù)據(jù)的請(qǐng)求(偽造數(shù)據(jù)攻擊),最終的壓力還是會(huì)全部涌向 mysql。這就是所謂的 緩存穿透。

解決方案:

在 redis 端設(shè)置 鍵值對(duì),以避免訪問(wèn) mysql。當(dāng)然缺點(diǎn)是如果 過(guò)多時(shí)會(huì)占用過(guò)多的內(nèi)存。我們可以給 key 設(shè)置過(guò)期時(shí)間,比如 exoire key 600ms, 停止攻擊后最終由 redis 自動(dòng)清除這些無(wú)用的 key ;

在 server 端設(shè)置一個(gè)布隆過(guò)濾器,將 mysql 中包含的 key 放入布隆過(guò)濾器中;布隆過(guò)濾器能過(guò)濾一定不存在的數(shù)據(jù)。

布隆過(guò)濾器

假設(shè)我么你現(xiàn)在提出一個(gè)需求:從海量數(shù)據(jù)中查詢某字符串是否存在。

在 c++ 中我們首先想到的應(yīng)該是使用 STL 中的 set 或者 map。

set 和 map

c++ 標(biāo)準(zhǔn)庫(kù)(STL)中的 set 和 map 結(jié)構(gòu)都是采?紅?樹實(shí)現(xiàn)的,它增刪改查的時(shí)間復(fù)雜度是:

o

(

l

o

g

2

n

)

o(log_{2}n)o(log2?n)

對(duì)于嚴(yán)格平衡?叉搜索樹(AVL),100w 條數(shù)據(jù)組成的紅?樹,只需要?較20次就能找到該值;對(duì)于10億條數(shù)據(jù)只需要?較30次就能找到該數(shù)據(jù);也就是查找次數(shù)跟樹的?度是?致的;

對(duì)于紅?樹來(lái)說(shuō)平衡的是?節(jié)點(diǎn)?度,所以研究?較次數(shù)需要考慮樹的?度差,最好情況某條樹鏈路全是?節(jié)點(diǎn),假設(shè)此時(shí)?度為 h1,最差情況某條樹鏈路全是?紅節(jié)點(diǎn)間隔,那么此時(shí)樹?度為 2*h1;

在紅?樹中每?個(gè)節(jié)點(diǎn)都存儲(chǔ) key 和 val 字段,key 是?來(lái)做?較的字段;紅?樹并沒(méi)有要求 key 字段唯?,在 set 和 map 實(shí)現(xiàn)過(guò)程中限制了 key 字段唯?。

另外 set 和 map 的關(guān)鍵區(qū)別是 set 不存儲(chǔ) val 字段;

優(yōu)點(diǎn):存儲(chǔ)效率?,訪問(wèn)速度?效;

缺點(diǎn):對(duì)于數(shù)據(jù)量?且查詢字符串?較?且查詢字符串相似時(shí)將會(huì)是噩夢(mèng);

unordered_map

c++ 標(biāo)準(zhǔn)庫(kù)(STL)中的 unordered_map 是采? hashtable 實(shí)現(xiàn)的;

構(gòu)成:數(shù)組 + hash 函數(shù);

它是將字符串通過(guò) hash 函數(shù)?成?個(gè)整數(shù)再映射到數(shù)組當(dāng)中;它增刪改查的時(shí)間復(fù)雜度是 o(1);

hash 函數(shù)的作?:避免插?的時(shí)候字符串的?較;hash函數(shù)計(jì)算出來(lái)的值通過(guò)對(duì)數(shù)組?度的取模能隨機(jī)分布在數(shù)組當(dāng)中;

hash 函數(shù)?般返回的是 64 位整數(shù),將多個(gè)?數(shù)映射到?個(gè)?數(shù)組中,必然會(huì)產(chǎn)?沖突;

如何選取 hash 函數(shù)?

選取標(biāo)準(zhǔn):

選取計(jì)算速度快;

哈希相似字符串能保持強(qiáng)隨機(jī)分布性(防碰撞);

murmurhash1,murmurhash2,murmurhash3,siphash( redis6.0 當(dāng)中使?,rust 等?多數(shù)語(yǔ)?選?的 hash 算法來(lái)實(shí)現(xiàn) hashmap),cityhash 都具備強(qiáng)隨機(jī)分布性;測(cè)試地址如下:https://github.com/aappleby/smhasher

負(fù)載因?:數(shù)組存儲(chǔ)元素的個(gè)數(shù)/數(shù)組?度;負(fù)載因?越?,沖突越?;負(fù)載因?越?,沖突越?;

hash沖突解決?案

鏈表法

引?鏈表來(lái)處理哈希沖突;也就是將沖突元素?鏈表鏈接起來(lái);這也是常?的處理沖突的?式;但是可能出現(xiàn)?種極端情況,沖突元素?較多,該沖突鏈表過(guò)?,這個(gè)時(shí)候可以將這個(gè)鏈表轉(zhuǎn)換為紅?樹;由原來(lái)鏈表時(shí)間復(fù)雜度 o(n) 轉(zhuǎn)換為紅?樹時(shí)間復(fù)雜度 ;那么判斷該鏈表過(guò)?的依據(jù)是多少?可以采?超過(guò)256(經(jīng)驗(yàn)值)個(gè)節(jié)點(diǎn)的時(shí)候?qū)㈡湵斫Y(jié)構(gòu)轉(zhuǎn)換為紅?樹結(jié)構(gòu);

開放尋址法

將所有的元素都存放在哈希表的數(shù)組中,不使?額外的數(shù)據(jù)結(jié)構(gòu);?般使?線性探查的思路解決;

當(dāng)插?新元素的時(shí),使?哈希函數(shù)在哈希表中定位元素位置;

檢查數(shù)組中該槽位索引是否存在元素。如果該槽位為空,則插?,否則進(jìn)行第 3 步;

在第 2 步檢測(cè)的槽位索引上加?定步?接著檢查第 2 步;

加?定步?分為以下?種:

i+1,i+2,i+3,i+4 ... i+n

i- ,i+ ,i- ,1+ ...

這兩種都會(huì)導(dǎo)致同類 hash 聚集;也就是近似值它的 hash 值也近似,那么它的數(shù)組槽位也靠近,形成 hash 聚集;第?種同類聚集沖突在前,第?種只是將聚集沖突延后;

另外還可以使?雙重哈希來(lái)解決上?出現(xiàn) hash 聚集現(xiàn)象。

在 .net HashTable 類的 hash 函數(shù) Hk 定義如下:

Hk(key) = [GetHash(key) + k * (1 + (((GetHash(key) >> 5) + 1) %(hashsize – 1)))] % hashsize

在此 (1 + (((GetHash(key) >> 5) + 1) % (hashsize – 1))) 與 hashsize互為素?cái)?shù)(兩數(shù)互為素?cái)?shù)表示兩者沒(méi)有共同的質(zhì)因?);執(zhí)?了 hashsize 次探查后,哈希表中的每?個(gè)位置都有且只有?次被訪問(wèn)到,也就是說(shuō),對(duì)于給定的 key,對(duì)哈希表中的同?位置不會(huì)同時(shí)使? Hi 和 Hj。

具體原理:https://www.cnblogs.com/organic/p/6283476.html

同樣的 hashtable 中節(jié)點(diǎn)存儲(chǔ)了 key 和 val,hashtable 并沒(méi)有要求 key 的??順序,我們同樣可以修改代碼讓插?存在的數(shù)據(jù)變成修改操作;

優(yōu)點(diǎn):訪問(wèn)速度更快;不需要進(jìn)?字符串?較;

缺點(diǎn):需要引?策略避免沖突,存儲(chǔ)效率不?;空間換時(shí)間;

總結(jié)

紅?樹和 hashtable 都不能解決海量數(shù)據(jù)問(wèn)題,它們都需要存儲(chǔ)具體字符串,如果數(shù)據(jù)量?,提供不了?百 G 的內(nèi)存;所以需要嘗試探尋不存儲(chǔ) key 的?案,并且擁有 hashtable 的優(yōu)點(diǎn)(不需要?較字符串);

布隆過(guò)濾器

布隆過(guò)濾器是?種概率型數(shù)據(jù)結(jié)構(gòu),它的特點(diǎn)是?效的插?和查詢,能明確告知某個(gè)字符串?定不存在或者可能存在;相?傳統(tǒng)的查詢結(jié)構(gòu)(例如:hash,set,map等數(shù)據(jù)結(jié)構(gòu))更加?效,占?空間更?;但是其缺點(diǎn)是它返回的結(jié)果是概率性的,也就是說(shuō)結(jié)果存在誤差的,雖然這個(gè)誤差是可控的;同時(shí)它不?持刪除操作;

組成:位圖(bit 數(shù)組)+ n 個(gè) hash 函數(shù)

原理:當(dāng)?個(gè)元素加?位圖時(shí),通過(guò) k 個(gè) hash 函數(shù)將這個(gè)元素映射到位圖的 k 個(gè)點(diǎn),并把它們置為 1;當(dāng)檢索時(shí),再通過(guò) k 個(gè) hash 函數(shù)運(yùn)算檢測(cè)位圖的 k 個(gè)點(diǎn)是否都為 1;如果有不為 1 的點(diǎn),那么認(rèn)為不存在;如果全部為1,則可能存在(存在誤差);

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-ahhhbjn3-1610794049644)(原理.png)]

在位圖中每個(gè)槽位只有兩種狀態(tài)(0 或者 1),?個(gè)槽位被設(shè)置為 1 狀態(tài),但不明確它被設(shè)置了多少次;也就是不知道被多少個(gè) str1 哈希映射以及是被哪個(gè) hash 函數(shù)映射過(guò)來(lái)的;所以不?持刪除操作;

在實(shí)際應(yīng)?過(guò)程中,布隆過(guò)濾器該如何使??要選擇多少個(gè) hash 函數(shù),要分配多少空間的位圖,存儲(chǔ)多少元素?另外如何控制假陽(yáng)率(布隆過(guò)濾器能明確?定不存在,不能明確?定存在,那么存在的判斷是有誤差的,假陽(yáng)率就是錯(cuò)誤判斷存在的概率)?

n -- 布隆過(guò)濾器中元素的個(gè)數(shù),如上圖 只有str1和str2 兩個(gè)元素 那么 n=2

p -- 假陽(yáng)率,在0-1之間 0.000000

m -- 位圖所占空間

k -- hash函數(shù)的個(gè)數(shù)

公式如下:

n = ceil(m / (-k / log(1 - exp(log(p) / k))))

p = pow(1 - exp(-k / (m / n)), k)

m = ceil((n * log(p)) / log(1 / pow(2, log(2))));

k = round((m / n) * log(2));

假定我們選取這四個(gè)值為:

n = 4000

p = 0.000000001

m = 172532

k = 30

四個(gè)值的關(guān)系:

在實(shí)際應(yīng)?中,我們確定 n 和 p,通過(guò)上?的計(jì)算算出 m 和 k;也可以在?站上選取合適的值:https://hur.st/bloomfilter

已知 k,如何選擇 k 個(gè) hash 函數(shù)?

// 采??個(gè)hash函數(shù),給hash傳不同的種?偏移值

// #define MIX_UINT64(v) ((uint32_t)((v>>32)^(v)))

uint64_t hash1 = MurmurHash2_x64(key, len, Seed);

uint64_t hash2 = MurmurHash2_x64(key, len, MIX_UINT64(hash1));

for (i = 0; i < k; i++) // k 是hash函數(shù)的個(gè)數(shù)

{

Pos[i] = (hash1 + i*hash2) % m; // m 是位圖的??

}

// 通過(guò)這種?式來(lái)模擬 k 個(gè)hash函數(shù) 跟我們前?開放尋址法 雙重hash是?樣的思路

總結(jié)

以上是生活随笔為你收集整理的mysql开启布隆过滤器_海量数据去重之布隆过滤器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。