我們先看這個正常的快取流程是怎麼樣的?如下圖所示:
可以看到,首先這個用戶訪問這個某東,然後這個某東去訪問這個Redis,如果Redis 有該訪問數據,就會直接回傳查緩存拿到的數據;如果Redis 快取沒有查到該數據,就會去MySql 資料庫中查詢,查詢到有結果把從MySql 中查到的數據同步至Redis 快取中去,同時會把這個查詢到的結果回回去。
這是一個簡單的正常的快取流程。那我們基於這個正常的快取流程,來看下什麼是快取的雪崩。
首先給大家舉個例子,就是在雙十一的時候,在某東買東西,進入它的這個首頁,由於是雙十一,首頁的訪問量是非常大的,所以首頁的很多資料都是緩存在redis 裡面的。
假設首頁資料儲存在redis 裡的100 個key,設定的快取失效時間是兩個小時,當在雙十一期間,購物超過兩個小時之後,這個首頁資料的redis 快取在這瞬間會全部失效,導致所有的請求都打到這個MySql 資料庫上,此時資料庫的存取壓力增大,造成這個MySql 資料庫回應不及時而掛掉,從而某東的首頁就沒辦法繼續對外提供服務了,然後東哥就特別不開心,把這次的技術負責人送去了非洲。
那麼透過這個舉例,我們來看下面這個圖:
#就是說使用者造訪某東,這個時候redis 裡面的key 大量失效,導致這個某東直接存取資料庫,把大量的請求都打到來資料庫,這種現象就是快取雪崩。簡單來說就是 redis 快取在同一時間大量失效,就像這個雪崩來了一樣。
那麼快取雪崩它的解決方案有幾種呢?下面來說:
設定這個快取的失效時間,不讓大量的key 在同一時間失效,也就是在設定這個快取的時候,可以將key 的失效時間分散開。
我們部署redis 一般是叢集部署的,可以把這些熱點的key 放到不同的節點上去,讓這些熱點的key 均勻的分佈在不同的redis 節點上。
還有就是比較暴力的方法,不設定這個快取失效的時間,讓 key 永遠不會失效。
接下來我們再來介紹什麼是快取穿透。
還是舉個例子:比如說某位老哥開發了一個網站,然後這個網站非常的受歡迎,某一天突然遭到了黑客瘋狂的攻擊,他的這個攻擊手段就是採用這個緩存穿透的原理。
大家都知道通常情況下,資料庫的主鍵是從0開始遞增的,是沒有負數的,那麼這位駭客就利用這點,他不斷的用 ID 小於零的參數發請求過來。這位老哥剛開始是把網站的所有資料放到了redis 快取裡面去,但是駭客是用ID 小於零的數來請求,redis 快取裡面並沒有這個ID 小於零的數據,這樣redis 就查不到這個結果,一旦redis 查不到結果就會去資料庫中查,那麼所有請求都會打到資料庫,而且會一直打到資料庫中去,因為redis 快取這層根本攔截不到這樣的資料。
redis 快取直接被這種資料穿透了,直接穿透到資料庫裡面。同樣我們來看下面這個圖:
首先這個惡意使用者存取某東,用id=-1 的資料去請求,然後這個id=-1 的資料在redis 快取裡面沒有查到,就到資料庫裡面查詢,也沒有查到該條數據,只能回傳空數據給前端了。
這個惡意使用者(駭客)用腳本不斷的發這個資料去請求,直接穿透 redis 打到這個資料庫上,這就是所謂的快取穿透。簡單來說,快取穿透就是指快取和資料庫中都沒有這樣的數據,一般出現這種情況都不是正常的使用者在存取。
那麼快取穿透的解決方案有以下幾點:
#請求如果穿透redis,直接到資料庫,那麼資料庫無論查出什麼結果,都寫回redis 快取裡面去,這樣下次用同一個參數發來請求的時候,就直接被redis 快取攔截掉了,就不回打到資料庫了。
對請求的參數做合法性校驗。
比較直接、簡單粗暴的方法,把這個 IP 拉黑。
最後是使用布隆過濾器,這是一個非常好的方式。
我們再來講最後一個問題,就是快取的擊穿。
還是拿雙十一來舉例:東哥在雙十一的時候,發話說想搞一個大活動,說想把自己20年前用的電腦拿出來拍賣,然後有巨多人對這台電腦有興趣,於是東哥決定在雙十一當天九點拍賣這台電腦,然後某東的開發程式設計師,把這台電腦資料放到了redis 快取裡,也就是對應redis 快取裡的一個key。
拍賣的時候,大家熱情都非常的高漲,持續拍賣了將近三個小時,還沒有結束這場線上拍賣,但是這台電腦對應的redis 緩存key 的失效時間是三個半小時。當大家拍賣到三個半小時的時候,這台電腦的緩存key 突然失效了,導致這個大量的拍賣請求在redis 裡面查不到數據,從而這些大量請求就會直接打到數據庫上,此時數據庫的瞬間壓力增大,造成反應不及時而掛掉。
這時候呢,東哥看到自己的這台電腦還沒拍賣出去,有點生氣,於是把這個程式設計師送去了非洲。
同樣我們也來看下面這個圖:
用戶訪問某東,然後去redis 請求某個拍賣秒殺商品,在快取沒有失效的時候,redis 可以把這個查詢到的快取key 的結果回回去,但是當這個快取的key 失效了,這個請求就會擊穿這個redis,直接打到資料庫上。
這裡大家注意的是,這裡是某一個熱點的key,大量的用戶請求不斷的訪問這個熱點的key,當這個熱點的key 突然失效,把請求都打到資料庫上,這個過程就是叫做快取擊穿了。 記住它是擊穿某個一個非常熱點的 key。
那麼這個快取擊穿的解決方案是:
讓這個熱點key 不過期,即不設定失效時間(不建議) 。
使用分散式鎖定,如果是單體應用的話使用互斥鎖(分散式鎖定後續文章會講)。
以上是Java MQ訊息佇列的基礎知識點有哪些?的詳細內容。更多資訊請關注PHP中文網其他相關文章!