快取穿透就是查詢一次不存在的資料,因為不存在,所以也不會往redis裡寫值,這樣一直查不存在的資料就會導致一直查資料庫,redis並沒有起到作用。
解決這個可以讓redis快取乙個空值或者快取乙個特殊的字串,但如果別人故意每次用不同的不存在的值惡意攻擊的話,即使快取了空值也還是沒有,
這就可以用布隆過濾器來解決
布隆過濾器就是一串01點陣圖,和幾個雜湊函式
就像這樣,插入資料時,資料a經過三個雜湊函式的計算,得到三個雜湊值,分別把三個位置上的0變成1
當取得時候,資料a如果經過三個雜湊函式算得的位置上都為1,就判斷a存在,所以這就有問題,如果判斷d的時候,得到的三個位置兩個是a佔的,乙個是b佔的,這樣還判斷d存在嗎?顯然是不對的
所以如果布隆過濾器判斷乙個元素存在,這個元素可能不存在
如果布隆過濾器判斷乙個元素不存在,這個元素一定不存在
如果想減少誤判率就需要增加01陣列的長度,和多加幾個雜湊函式。
布隆過濾器的缺點:
1.布隆過濾器也是不能修改和刪除的,因為如果hello和你好算得的雜湊值相同,然後把你好刪了,這樣就把hello也誤刪了
2.查詢效能弱:布隆過濾器使用多個hash函式計算位圖多個不同位點,由於多個位點在記憶體中不連續,cpu定址花銷較大。
3.空間利用率低
還有一種可以簡單實現刪除的過濾器——布穀鳥過濾器,不過他的刪除也是有缺陷的
布穀鳥過濾器不是用位圖實現的,使用的是一維陣列,陣列裡面存放的是資料的指紋。
布穀鳥過濾器是可以鳩佔鵲巢的,還拿上面的圖來說
布穀鳥過濾器有三個雜湊函式,兩個雜湊對映函式,和乙個計算指紋的函式
h3(key) = key』s fingerprint = hash(key)
h1(key) = hash1(key)
h2(key) = h1(key) ^ h1(key』s fingerprint)
資料a經過兩個雜湊對映函式,得到兩個位置,如果資料a在兩個位置裡隨機選擇乙個位置,如果這個位置沒人就直接佔據這個位置,如果已經有人了,就把這個位置上的人踢走,如果給他重新選擇乙個位置
重新選位置的時候,另乙個位置可以通過指紋的雜湊值和位置的雜湊值異或得來
但這樣也有問題,如果陣列太過擁擠,就會導致踢了幾十次依然沒有給每個人找到位置。
改良的方案之一是增加 hash 函式, 讓每個元素不止有兩個巢, 這樣可以大大降低碰撞的概率, 將空間利用率提高到 95% 左右.
還有個方案是給每個位置上設定多個座位,就像二維陣列一樣, 這樣不會馬上就擠來擠去. 也能大大降低碰撞概率, 空間利用率雖然比第一種改良方案稍低(約為 85%), 但cpu 快取的利用率會提高不少.
刪除的話,就是找到對應位置上的自己的指紋,然後刪除掉
但這樣的刪除,如果通過雜湊函式計算的指紋是一樣的,位置也是一樣的,就會造成誤刪
而且布穀鳥過濾器不能連續插入相同的資料,如果一直插入1,假設有兩個位置,每個位置有四個座位,當插入第九個1的時候,就會導致沒地方去了
所以插入相同的資料不能超過kb,k是位置數,b是座位數。
Redis 布隆過濾器
實現原理 對的資料肯定是對的,錯的資料不能保證是對的。解釋如下 之前新增到容器中的資料,再次進行判斷是不是在這裡面,因為來過,槽位肯定我為1,所以判斷是不會出現問題的。容器中不存在,判斷是不是在容器中,可能其他的資料通過hash函式執行後把槽位占用了,所以存在一定的誤差。不能保證一定沒問題。hash...
Redis 布隆過濾器
想知道某乙個值是不是已經在 hyperloglog 結構裡面了,它就無能為力了,它只提供了 pfadd 和 pfcount 方法,沒有提供 pfcontains 這種方法。講個使用場景,比如我們在使用新聞客戶端看新聞時,它會給我們不停地推薦新的內容,它每次推薦時要去重,去掉那些已經看過的內容。問題來...
redis 布隆過濾器
為了應對redis快取穿透有三個大致方案 做好引數校驗,快取無效key,以及布隆過濾器。通過布隆過濾器我們可以非常方便地判斷乙個給定資料是否存在於海量資料中。我們需要的就是判斷 key 是否合法 具體是這樣做的 把所有可能存在的請求的值都存放在布隆過濾器中,當使用者請求過來,先判斷使用者發來的請求的...