使用緩存需要注意的幾個問題

前言

現在的網站基本上都會加入緩存層來提升性能表現,前端請求會先去緩存層請求數據,若未命中緩存纔會去請求數據庫層,這樣可以大大減少去數據庫層請求的連接數,減少數據庫壓力,加快接口響應速度。

緩存雖然是性能利器,但在高併發情況下使用不當可能會導致以下幾個問題。

緩存穿透

定義:以最常用的緩存中間件Redis爲例,我們將緩存數據以K/V的形式存儲在Redis中,通過查詢key是否在Redis中存在來判斷是否命中緩存。一般情況下我們只將查詢結果不爲空的數據進行緩存。緩存穿透指的是前端請求的數據在緩存中一定不存在,導致請求直接訪問數據庫,若惡意構造大量這樣的請求訪問系統,那麼數據庫有可能會因爲訪問量過大而被壓垮。

解決方案

1.對查詢結果爲空的key也進行緩存。當我們緩存空數據時,再有相同條件的查詢請求時,直接返回空即可而不必去請求數據庫。由於導致結果爲空值的查詢條件可能會比較多,這樣會導致緩存中存在大量value爲空值的K/V對,爲了解決這個問題,我們可以將數據爲空的緩存的過期時間設置的較短一些,使其快速過期,以釋放內存空間。

2.使用布隆過濾器(對布隆過濾器不清楚的同學請看我之前的這篇文章布隆過濾器)。我們按照查詢條件去查詢數據,查詢條件一定是有限的,我們可以將所有可能的查詢參數組合都放入布隆過濾器中,在controller中進行校驗,在布隆過濾器中不存在的參數組合則會被過濾掉直接返回。這樣連緩存層都不用訪問了。

緩存雪崩

定義:緩存雪崩指的是緩存服務器重啓或者緩存服務器宕機,那麼此時所有的請求都會到達數據庫層,導致數據庫被壓垮。

解決方案:使用緩存服務器集羣,保證緩存的高可用,這個方案更偏向於架構與運維一些。

熱點key

定義:熱點key其實可以看做緩存雪崩的一個子類,這裏把他分出來是爲了結構更加清晰一點。一般情況下我們會給緩存設置過期時間,熱點key指的是對於一些請求量較高的熱點數據而言,一旦集中過期,此時將會有大量請求落在數據庫層,從而可能會導致數據庫崩潰。

解決方案

1.錯開過期時間。爲了防止一批熱點key同時失效,我們可以爲這些key設置不同的過期時間,使其過期時間儘量錯開。

2.使用互斥鎖。利用Redis的setnx命令或者多參數的set命令實現互斥鎖,只讓一個線程去查詢數據庫構建緩存,其他線程等待該線程執行完成,重新從緩存獲取數據就可以了。

3.永不過期。指的是不爲緩存設置過期時間,只在value中存一個邏輯上的過期時間,每次get發現邏輯過期時間小於當前時間則新建一個線程去數據庫重新獲取數據構建緩存。

4.接口限流。這個方案就不涉及緩存操作相關代碼了,就純粹是做接口上的限流操作。關於如何做限流請看我之前的這篇文章關於限流

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