前言
雖然緩存被認為是軟件系統的性能助推器,但如果處理不當,它也容易出現錯誤。 在本文中,我將介紹 3 個有時可能會造成災難性后果的常見緩存問題,希望大家在架構上引入緩存時,需要考慮到。
緩存擊穿
緩存故障 當緩存鍵過期時會發生緩存故障,并且多個請求同時訪問數據庫以查找相同的鍵。 讓我們來看看它是如何工作的:
- 熱緩存鍵過期。
- 多個并發請求進來搜索同一個鍵。
- 服務器向數據庫發起多個并發請求以查找相同的鍵。
緩存擊穿會顯著增加數據庫的負載,尤其是當許多熱鍵同時過期時。 下面是解決這個問題的2種解決方案:
- 獲取搜索到的key的分布式鎖,當一個線程試圖更新緩存時,其他線程需要等待。
- 利用Refresh-ahead 策略異步刷新熱數據,使熱鍵永不過期。
緩存穿透
緩存穿透 當搜索到的key?既不在緩存中, 也不在數據庫中時,就會發生**緩存穿透,**連數據庫都穿透過去了。 讓我們來看看它是如何工作的,當key既不在緩存中也不在數據庫中時,就會發生這種情況。
- 當用戶查詢key時,應用程序由于緩存未命中而去查詢數據庫數據庫。
- 由于數據庫不包含該key并返回空結果,因此該key也不會被緩存。
- 因此,每個查詢最終都會導致緩存未命中,而命中數據庫,直接進行查庫。
雖然乍一看這似乎微不足道,但攻擊者可以通過使用此類密鑰啟動大量搜索來嘗試破壞你的數據庫。 為了解決這個問題,我們可以:
- 緩存過期時間較短的空結果。
- 使用布隆過濾器。在查詢數據庫之前,應用程序在布隆過濾器中查找key,如果key不存在則立即返回。
緩存雪崩
當對數據庫的請求突然激增時,就會發生緩存雪崩。 這發生在:
- 許多緩存數據同時過期。
- 緩存服務宕機,所有請求都直接訪問數據庫。
數據庫流量的突然激增可能會導致級聯效應,并可能最終導致您的服務崩潰。 下面是一些常見的解決方案:
- 調整緩存鍵的過期時間,使它們不會同時過期。
- 使用Refresh-ahead 策略異步刷新熱數據,使其永不過期。
- 使用緩存集群來避免單點故障。當主節點崩潰時,其中一個副本被提升為新的主節點。
總結
雖然這些緩存問題起初看起來微不足道,但有時可能會對我們的下游客戶端和依賴項產生級聯效應。事先了解它們可以讓我們設計一個更強大的系統,也可以簡化我們的故障排除過程。