【Redis】快取雪崩、快取擊穿、快取穿透(原因 + 分析 + 解決方案)
theme: channing-cyan highlight: vs
攜手創作,共同成長!這是我參與「掘金日新計劃 · 8 月更文挑戰」的第17天,點選檢視活動詳情 >>
快取雪崩、快取擊穿、快取穿透
相信很多使用過redis的朋友們都對redis中的快取雪崩、擊穿、穿透有一定的瞭解,那麼今天就讓我們一起來學習一下造成這三個問題的原因以及相應的解決方法。
一、快取雪崩
為什麼會導致快取雪崩?
一般來說,redis在架構中充當快取的角色,對於客戶請求的資料,如果redis中有快取且快取未過期,則會直接由redis將資料返回,而不需要到達mysql資料庫;只有在redis中沒有快取(或者快取過期了),客戶請求才會到達mysql。
整個過程如下圖所示:
快取雪崩的出現就是因為在同一時間內redis中有大量的key過期,或者redis宕機,而偏偏這時候恰好有大量的使用者請求到來,此時的redis已經無法處理了,所以這些大量的請求都會到達mysql資料庫。
因為大量的請求一時間到達,導致資料庫壓力驟增,嚴重的情況下可能導致資料庫宕機,甚至引發一系列連鎖問題。
以上所討論的就是快取雪崩的情況。
快取雪崩的解決方案
情況一:大量key同一時間過期所致
在這種情況下,我們的一個很基本的想法就是避免大量的key的同一個時間點內過期,讓key的過期時間儘可能均勻。
- 均勻地設定過期時間:redis中key的過期時間我們可以自己設定的
- 互斥鎖:在一個使用者請求發現redis無法處理的時候,加鎖,保證同一時間內只有一個請求到達mysql,從而構建新的快取,待快取構建成功後,釋放鎖,則後續的請求就可以在redis中處理了
- 雙key策略:主key設定過期時間,備key則不設定過期時間;主key過期了,此時請求來到則返回備key,並更新快取,同時更新主、備key的資料
- 後臺更新快取:這種方案有兩種實現: 其一、key不設定過期時間,但開啟一個後臺執行緒定期檢查快取是否有效;若失效,則立馬更新快取 其二、在一個使用者請求到來發現快取失效後,由訊息佇列發訊息通知後臺程序更新快取。
情況二:redis宕機所致
這種情況一般是redis故障宕機所引起的快取雪崩問題。
- 採用服務熔斷或請求限流機制,暫停業務層訪問,或者直接返回錯誤。請求限流是指限制可到達資料庫的使用者請求的個數,避免資料庫壓力驟增
- 構建redis快取高可靠叢集:假如主節點宕機後,會有從節點自動升級為主節點,不影響redis叢集的可用性。
二、快取擊穿
快取擊穿是由於redis中熱點資料過期,導致大量使用者請求到達mysql資料庫。
快取雪崩包含大量key在同一時間內過期或者redis宕機兩種情況,而快取擊穿是快取雪崩第一種情況中的一個特殊情況;因為它強調的是熱點的key過期。
其實直白點來說,快取擊穿可以看做是快取雪崩的一個子集(快取擊穿是快取雪崩情況的一部分)
也正因為這樣,所以快取擊穿可以用快取雪崩中的以下兩種方案解決:
- 互斥鎖
- 後臺更新快取
三、快取穿透
快取穿透是指使用者所想訪問的資料既不在redis中,也不在mysql資料庫中,在這種情況下,一樣會有大量的請求到達資料庫中,導致資料庫壓力驟增(但是資料庫中也沒有相關資料的,無法正常返回的)
- 限制非法請求:防止大量惡意請求訪問redis或者資料庫中都不存在的資料
- 快取預設值(空值):當發現出現快取穿透的資料,可以在redis中給它設定預設快取。
- 採用布隆過濾器快速判斷資料是否存在