Redis-緩存雪崩、擊穿、穿透

提到Redis我相信各位在面試,或者實際開發過程中對緩存雪崩,穿透,擊穿也不陌生吧,就 算沒遇到過但是你肯定聽過,那三者到底有什麼區別,我們又應該怎麼去防止這樣的情況發生 呢,我們有請下一位受害者。

面試開始

一個大腹便便,穿着格子襯衣的中年男子,拿着一個滿是劃痕的mac向你走來,看着快禿 頂的頭髮,心想着肯定是尼瑪頂級架構師吧!但是我們腹有詩書氣自華,虛都不虛

小夥子我看你的簡歷上寫到了Redis,那麼我們直接開門見山,直接 懟常見的幾個大問題,Redis雪崩瞭解麼?

帥氣迷人的面試官您好,我瞭解的,目前電商首頁以及熱點數據都會去做緩存 ,一般緩存都 是定時任務去刷新,或者是查不到之後去更新的,定時任務刷新就有一個問題。

舉個簡單的例子:如果所有首頁的Key失效時間都是12小時,中午12點刷新的,我零點有個秒 殺活動大量用戶湧入,假設當時每秒 6000 個請求,本來緩存在可以扛住每秒 5000 個請求, 但是緩存當時所有的Key都失效了。此時 1 秒 6000 個請求全部落數據庫,數據庫必然扛不 住,它會報一下警,真實情況可能DBA都沒反應過來就直接掛了。此時,如果沒用什麼特別的 方案來處理這個故障,DBA 很着急,重啓數據庫,但是數據庫立馬又被新的流量給打死了。 這就是我理解的緩存雪崩。

我刻意看了下我做過的項目感覺再吊的都不允許這麼大的QPS直接打DB去,不過沒慢SQL加 上分庫,大表分表可能還還算能頂,但是跟用了Redis的差距還是很大

同一時間大面積失效,那一瞬間Redis跟沒有一樣,那這個數量級別的請求直接打到數據庫幾 乎是災難性的,你想想如果打掛的是一個用戶服務的庫,那其他依賴他的庫所有的接口幾乎都 會報錯,如果沒做熔斷等策略基本上就是瞬間掛一片的節奏,你怎麼重啓用戶都會把你打掛, 等你能重啓的時候,用戶早就睡覺去了,並且對你的產品失去了信心,什麼垃圾產品。

面試官摸了摸自己的頭髮,嗯還不錯,那這種情況咋整?你都是怎麼 去應對的?

 

處理緩存雪崩簡單,在批量往Redis存數據的時候,把每個Key的失效時間都加個隨機值就好 了,這樣可以保證數據不會在同一時間大面積失效,我相信,Redis這點流量還是頂得住的。

setRedis(Key,value,time + Math.random() * 10000);

如果Redis是集羣部署,將熱點數據均勻分佈在不同的Redis庫中也能避免全部失效的問題, 不過本渣我在生產環境中操作集羣的時候,單個服務都是對應的單個Redis分片,是爲了方便 數據的管理,但是也同樣有了可能會失效這樣的弊端,失效時間隨機是個好策略。

或者設置熱點數據永遠不過期,有更新操作就更新緩存就好了(比如運維更新了首頁商品,那 你刷下緩存就完事了,不要設置過期時間),電商首頁的數據也可以用這個操作,保險。

那你瞭解緩存穿透和擊穿麼,可以說說他們跟雪崩的區別麼?

嗯,瞭解,我先說一下緩存穿透吧,緩存穿透是指緩存和數據庫中都沒有的數據,而用戶不斷 發起請求,我們數據庫的 id 都是1開始自增上去的,如發起爲id值爲 -1 的數據或 id 爲特別大 不存在的數據。這時的用戶很可能是攻擊者,攻擊會導致數據庫壓力過大,嚴重會擊垮數據 庫。

小點的單機系統,基本上用postman就能搞死,比如我自己買的阿里服務

像這種你如果不對參數做校驗,數據庫id都是大於0的,我一直用小於0的參數去請求你,每次 都能繞開Redis直接打到數據庫,數據庫也查不到,每次都這樣,併發高點就容易崩掉了。

至於緩存擊穿嘛,這個跟緩存雪崩有點像,但是又有一點不一樣,緩存雪崩是因爲大面積的緩 存失效,打崩了DB,而緩存擊穿不同的是緩存擊穿是指一個Key非常熱點,在不停的扛着大並 發,大併發集中對這一個點進行訪問,當這個Key在失效的瞬間,持續的大併發就穿破緩存, 直接請求數據庫,就像在一個完好無損的桶上鑿開了一個洞。

面試官露出欣慰的眼光,那他們分別怎麼解決

緩存穿透我會在接口層增加校驗,比如用戶鑑權校驗,參數做校驗,不合法的參數直接代碼 Return,

比如:id 做基礎校驗,id <=0的直接攔截等。

這裏我想提的一點就是,我們在開發程序的時候都要有一顆“不信任”的心,就是不要相信任 何調用方,比如你提供了API接口出去,你有這幾個參數,那我覺得作爲被調用方,任何可能 的參數情況都應該被考慮到,做校驗,因爲你不相信調用你的人,你不知道他會傳什麼參數給 你。

舉個簡單的例子,你這個接口是分頁查詢的,但是你沒對分頁參數的大小做限制,調用的人萬 一一口氣查 Integer.MAX_VALUE 一次請求就要你幾秒,多幾個併發你不就掛了麼?是公司 同事調用還好大不了發現了改掉,但是如果是黑客或者競爭對手呢?在你雙十一當天就調你這 個接口會發生什麼,就不用我說了吧。這是之前的Leader跟我說的,我覺得大家也都應該了 解下。

從緩存取不到的數據,在數據庫中也沒有取到,這時也可以將對應Key的Value對寫爲null、位 置錯誤、稍後重試這樣的值具體取啥問產品,或者看具體的場景,緩存有效時間可以設置短 點,如30秒(設置太長會導致正常情況也沒法使用)。

這樣可以防止攻擊用戶反覆用同一個id暴力攻擊,但是我們要知道正常用戶是不會在單秒內發 起這麼多次請求的,那網關層Nginx本渣我也記得有配置項,可以讓運維大大對單個IP每秒訪 問次數超出閾值的IP都拉黑。

那你還有別的辦法麼?

還有我記得Redis還有一個高級用法布隆過濾器(Bloom Filter)這個也能很好的防止緩存穿 透的發生,他的原理也很簡單就是利用高效的數據結構和算法快速判斷出你這個Key是否在數 據庫中存在,不存在你return就好了,存在你就去查了DB刷新KV再return。

那又有小夥伴說了如果黑客有很多個IP同時發起攻擊呢?這點我一直也不是很想得通,但是一 般級別的黑客沒這麼多肉雞,再者正常級別的Redis集羣都能抗住這種級別的訪問的,小公司 我想他們不會感興趣的。把系統的高可用做好了,集羣還是很能頂的。

 

緩存擊穿的話,設置熱點數據永遠不過期。或者加上互斥鎖就能搞定了

代碼我肯定幫你們準備好了

面試結束

 

在此感謝B站up主,三太子敖丙,大家可以多多關注他哦。很牛的一位大佬。-->摘自B站 三太子敖丙

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章