Redis快取穿透出現原因及解決方案
在併發式的專案當中,一定要考慮一個快取穿透的情況。那麼什麼是快取穿透呢?簡單的說來,就是當大量請求的key根本不在快取當中,所以導致了請求直接到了資料庫上,根本沒有經過快取這一層。比如一個黑客故意製造我們快取中不存在的key傳送大量的請求,就會導致請求直接落到資料庫上。
也就是說,快取穿透就是:1.快取層不命中。2,儲存層不命中,不將空的結果寫回快取。3,返回空結果給客戶端。
一般mysql的預設最大連線數是150左右,當然這個是可以用show variables like ‘%max_connections%'命令來檢視。
當然這只是一個指標,cpu磁碟記憶體網路等等原因都影響了他的併發能力,所以一般3000的併發請求就可以殺死大部分的資料庫。
那麼出現快取穿透的時候需要怎麼應對呢?
1)最基本的方式就是做好引數校檢,比如不合法的請求就直接丟擲異常資訊給客戶端,就比如設定查詢條件id不能小於0或者傳入郵箱格式不正確時直接返回錯誤訊息給客戶端。但是這樣還是會出現快取穿透的現象。那麼還可以通過下面幾個方案來解決:
2)快取無效的key,如果資料庫和快取都找不到某個key的資料,就直接寫一個到redis中並設定它的過期時間 set key value EX 10086。這種方式可以解決請求的key變化不頻繁的情況,如果遇到專門的黑客攻擊就不能解決這個情況。但是如果依然想用這個方法的話,那麼在設定過期時間的時候,時間短一點,比如是一分鐘。多說一句設定key的格式一般是:表名:列名:主鍵名:主鍵。
3)利用布隆過濾器:布隆過濾器是一個非常神奇的資料結構,通過這個過濾器可以幫助我們非常方便的去判斷一個給定的資料是否存在於海量的資料當中。所以布隆過濾器在針對資料去重和驗證資料的合法性時是非常有用的,布隆過濾器的實質就是一個bit(位)陣列。也就是說每一個存進的資料都僅僅只佔一位,在資料結構上來說相當於List、Map、Set等資料結構,但是佔用的空間更少而且效率更高,但是缺點是它返回的值是概率性的,並不是多麼的準確。當一個元素加入到布隆過濾器的時候:1.使用布隆過濾器當中的雜湊函式對元素值進行計算,得到雜湊值。2.根據得到的雜湊值,在位陣列中把對應的下標改為1。那麼設定完成之後,我們要怎麼判斷一個元素是否存在於布隆過濾器當中呢?
首先我們要根據給定的元素再次進行hash計算;得到值之後判斷陣列中的每個元素是否都為1,如果值都為1的話,那麼說明這個值在過濾器當中,如果不為1的話,就說明不再過濾器當中。
舉個非常簡單的例子
如上圖所示,當字串要加入到布隆過濾器當中時,該事務首先由多個雜湊函式生成不同的雜湊值,然後在對應的位陣列的下標的元素設定位1,當二次儲存相同的字串時,因為先前的對應位置已經存在,所以在去重的時候非常方便。如果我們需要判斷某個字串是否在布隆過濾器當中時,只需要對給定的字串再次進行相同的雜湊計算,得到的值判斷是否為1,從而判斷資料是否存在於布隆過濾器當中,那麼假如布隆過濾器說明一個數據存在時,很小的概率會誤判,但是如果說明一個數據不存在時,那麼一定是不存在的。
那麼通過這個原理,利用redis布隆過濾器來將所有可能存在請求的值放在布隆過濾器當中,當用戶請求時,直接判斷使用者傳送來的請求是否存在於布隆過濾器中,不存在的話,直接返回請求引數錯誤資訊給客戶,存在的話就繼續往下面走流程。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。