前言
最近看到redis的時候,發現有如下疑問:什麼是redis雪崩、穿透和擊穿?產生這些問題該怎麼辦?
緩存雪崩
是什麼
如果你在使用redis的時候,遇到如下兩種情況,可能你就遇到緩存雪崩了。
情況一
系統A,每天高峯併發量每秒5000個請求,緩存可以抗住4000請求,但是這時redis宕機了,此時每秒5000個請求的壓力都到了數據庫中,數據庫必然扛不住,然後就掛了。就算是DBA重啓數據庫,仍然會新的流量給打死,這就是緩存雪崩了
情況二
系統B,每天高峯併發量每秒5000個請求,緩存可以抗住4000請求,這時所有的key值失效了,也就是過期時間到了,這時每秒5000個請求的壓力都到了數據庫中,數據庫必然扛不住,也會掛掉。這也是緩存雪崩。
該如何解決呢?
如果你在使用redis的時候,遇到如下兩種情況,可能你就遇到緩存雪崩了。
緩存雪崩的事前、事中、事後的解決方案:
- 事前:redis高可用,主從+哨兵,redis cluster,避免全盤崩潰。
- 事中:本地ehcache緩存+Hystrix限流/降級,避免MySQL被打死。
- 事後:redis持久化,一旦重啓,自動從磁盤上加載數據,快速恢復緩存數據。
- 其他解決方法:java鎖實現限流、數據預熱、給緩存的失效時間,加上一個隨機值,避免集體失效、做二級緩存,或者雙緩存策略、緩存永不過期
參考資料:解決redis緩存穿透和緩存雪崩
用戶發送一個請求,系統受到請求後,先查本地ehcache緩存,如果沒查到再查redis。如果ehcache和redis都沒有,再查數據庫,將數據庫中的結果,寫入ehcache和redis中。
限流組件,可以設置每秒的請求,有多少能通過組件,剩餘的未通過的請求,怎麼辦?走降級!可以返回一些默認的值,或者友情提示,或者空白的值。
好處:
- 數據庫絕對不會死,限流組件確保了每秒只有多少個請求能通過。
- 只要數據庫不死,就是說,對用戶來說,2/5的請求都是可以被處理的。
- 只要有2/5的請求可以被處理,就意味着你的系統沒死,對用戶來說,可能就是點擊幾次刷不出來頁面,但是多點幾次,就可以刷出來一次。
緩存穿透
是什麼
對於系統A,假設每秒5000個請求,結果其中4000個請求是黑客發來的惡意攻擊。那4000個請求在緩存中查詢不到,然後進入到數據庫中也查詢不到。請求每次都“視緩存於無物”,直接查詢數據庫,也能直接把數據庫打死。
該如何解決呢?
- 每次系統A從數據庫中查詢不到,就寫一個空值到緩存裏去,以請求參數爲key,null值爲value,設置過期時間,這樣下次有相同的key來訪問的時候,在緩存失效之前,都可以直接從緩存中取數據。
- 設置布隆過濾:將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被這個bitmap攔截掉,從而避免了對底層數據庫的查詢壓力。
緩存擊穿
是什麼
緩存擊穿,就說某個熱點key,訪問非常頻繁,處於集中式高併發訪問的情況,當這個key在失效的瞬間,大量的請求就擊穿了緩存,直接訪問數據庫,就像是在一道屏障上鑿開了一個洞。
該如何解決呢?
- 將熱點數據設置爲永不過期
- 基於redis 或者 zookeeper 實現互斥鎖,等待第一個請求構建完緩存之後,再釋放鎖,進而其他請求才能通過該key訪問數據。
黑色背景 |
小結
有關redis的內容,在繼續深入的過程中,加深理解。明白爲什麼,該如何做。
感謝您的閱讀~~