技術架構師,將整間企業的IT開發流程至維運管理,視為一個大型系統進行規劃。並分為四個面向進行發展: - [開發平臺]:構建高度重用的共用模組和服務,並在多個專案項目和應用系統中使用,以提高開發效率並降低維護成本。 - [DevOps平臺]:建構連續集成、連續交付的工作環境,將開發與維運團隊更緊密地連 ...
緩存擊穿、穿透、雪崩及解決方案
Redis是一種高性能的鍵值型資料庫,它可以用來實現緩存功能,提高應用的響應速度和承載能力。但是,使用Redis緩存也會遇到一些常見的問題,比如緩存擊穿、緩存穿透、緩存雪崩。這些問題都會影響緩存的效率和穩定性,所以需要瞭解它們的原因和解決方案,保障Redis能夠正常運行。
擊穿、穿透、雪崩的意思
擊穿、穿透、雪崩這三個詞語很容易混淆,本文先對詞語進行理解,再講解技術
擊穿:擊穿拆開後,是擊和穿。擊意為敲打,或做類似敲打的動作。穿意為穿透
擊是什麼?如下圖,攻擊的意思
穿是什麼?如下圖,穿透,造成的效果就是個洞
雪崩的意思很簡單,就是一個字多,如下圖
白話講解一下,擊穿就是先擊後穿;穿透就是穿透,有個洞;雪崩就是多,很多很多
再從技術角度說明擊穿、穿透、雪崩
擊穿意為先擊後穿。熱點數據存在,且能夠擊中。但是由於熱點數據失效從而訪問資料庫
穿透意為直接穿。由於訪問不存在的數據,從而直接訪問資料庫
雪崩意為多,大量。大量緩存同時失效,從而直接訪問資料庫
緩存擊穿
緩存擊穿的定義:某個熱點數據在緩存中過期或失效時,大量的請求同時訪問該數據,導致資料庫壓力過大甚至崩潰的現象。通常會發生在數據更新頻率較高或者緩存設置了相同的過期時間的時候。
實際上可以這麼理解:應該有的數據但是沒讀到,從而擊穿了緩存,直接訪問資料庫
可採取的方案:
- 不設置過期時間或設置較長的過期時間:這樣可以避免熱點數據同時失效,但是也會增加記憶體占用和數據不一致的風險
- 定時更新。比如這個熱點數據的過期時間是 2 小時,那麼每到 1小時50 分鐘時,通過定時任務去更新這個熱點 key,並重新設置其過期時間
- 互斥鎖:當緩存中沒有數據時,只允許一個線程去資料庫查詢並更新緩存,其他線程等待該線程完成後再從緩存中獲取數據。這樣可以減少對資料庫的併發訪問,但是也會降低系統的吞吐量和響應速度
- 分散式鎖:當多個Redis節點存在時,可以使用分散式鎖來保證只有一個節點去資料庫查詢並更新緩存,其他節點等待該節點完成後再從緩存中獲取數據。這樣可以避免多個Redis節點同時訪問資料庫,但是也會增加系統的複雜度和延遲
緩存穿透
緩存穿透的定義:
用戶查詢一個不存在的數據,導致緩存中沒有該數據,每次都要去資料庫查詢,而資料庫中也沒有該數據,造成無效的查詢和資源浪費的現象。通常會發生在用戶惡意攻擊或者參數校驗不嚴格的時候
實際上可以這麼理解:不應該有的數據非要讀,從而穿透了緩存,直接訪問資料庫
可採取的方案:
- 業務層校驗。用戶發過來的請求,根據請求參數進行校驗,對於明顯錯誤的參數,直接攔截返回。比如請求參數為主鍵自增 id ,那麼對於請求小於 0 的 id 參數, 明顯不符合業務邏輯。
- 緩存空值:當資料庫中沒有查詢到數據時,仍然將空值或者預設值寫入緩存,並設置一個較短的過期時間。這樣可以減少對資料庫的訪問次數,但也會占用一定的記憶體
- 使用布隆過濾器:布隆過濾器是一種概率型的數據結構,它可以判斷一個元素是否可能存在於一個集合中。可以將所有可能存在的數據的鍵值哈希到一個足夠大的點陣圖中,當用戶查詢一個數據時,先用布隆過濾器判斷該鍵值是否可能存在,如果不存在則直接返回,如果存在則再去緩存和資料庫中查詢。這樣可以有效地攔截不存在的數據請求,但是也會有一定的誤判率和記憶體開銷
緩存雪崩
緩存雪崩的定義:在某個時間點,大量的緩存數據同時失效或者緩存伺服器宕機,導致所有的請求都要去資料庫查詢,造成資料庫壓力過大甚至崩潰的現象。這種情況通常發生在緩存設置了相同或者相近的過期時間或者緩存伺服器遭遇意外故障的場景下。
實際上可以這麼理解:大量數據讀取,從而使緩存雪崩,直接訪問資料庫
為了防止緩存雪崩,可以採用以下幾種方法:
- 設置不同的過期時間。可以給緩存設置不同或者隨機的過期時間,避免大量的緩存同時失效,造成資料庫壓力突增
- 緩存預熱:對於即將來臨的大量請求,可以將數據提前緩存在Redis中,並設置不同的過期時間
- 使用多級緩存:可以構建多級緩存架構,比如Nginx緩存+Redis緩存+本地緩存等,當某一級緩存出現問題時,可以從其他級別的緩存中獲取數據,增加系統的容錯能力
- 使用限流熔斷:可以利用一些限流和熔斷組件,對請求進行限流和降級處理,當請求超過系統能承受的閥值時,直接拒絕或者返回預設值,保護資料庫不被打垮
- 使用集群和負載均衡:可以將Redis部署成集群模式,並使用負載均衡組件,比如LVS、HAProxy等,對請求進行分發和轉發,提高Redis的可用性和併發能力
總結
本文介紹了緩存擊穿、緩存穿透和緩存雪崩三種問題及解決方案。通過本文,可以瞭解到:
- 緩存擊穿:先擊後穿
- 緩存擊穿的解決方案有:設置熱點數據永不過期、定時更新、分散式
- 緩存穿透:將緩存穿了個洞
- 緩存穿透的解決方案有:業務層校驗、緩存空值、布隆過濾器
- 緩存雪崩:大量失效Key
- 緩存雪崩的解決方案有:設置不同的過期時間、緩存預熱、多級緩存、限流熔斷、集群和負載均衡