redis緩存穿透、緩存擊穿、緩存雪崩
阿新 • • 發佈:2019-02-13
用戶 時間 隊列 每次 設計 如果 問題 取數據 最長
緩存穿透
緩存穿透是指查詢一個一定不存在的數據,由於緩存是不命中時需要從數據庫查詢,查不到數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到數據庫去查詢,造成緩存穿透。
解決辦法:
預校驗
在控制層對查詢參數先進行校驗,不符合則丟棄。
布隆過濾
將所有可能查詢的參數添加到BloomFilter中,一定不存在的記錄就會被BloomFilter過濾掉,從而避免了對底層存儲系統的查詢壓力。
緩存空對象
如果一個查詢返回的數據為空(不管是數據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。
緩存空對象會有兩個問題:
- 空值做了緩存,意味著緩存層中存了更多的鍵,需要更多的內存空間 ( 如果是攻擊,問題更嚴重 ),比較有效的方法是針對這類數據設置一個較短的過期時間,讓其自動剔除。
- 緩存層和存儲層的數據會有一段時間窗口的不一致,可能會對業務有一定影響。例如過期時間設置為5分鐘,如果此時存儲層添加了這個數據,那此段時間就會出現緩存層和存儲層數據的不一致,此時可以利用消息系統或者其他方式清除掉緩存層中的空對象。
緩存擊穿
緩存擊穿是指緩存中沒有但數據庫中有的數據(一般是緩存時間到期),這時由於並發用戶特別多,同時讀緩存沒讀到數據,又同時去數據庫去取數據,引起數據庫壓力瞬間增大,造成過大壓力
解決方案:
- 設置熱點數據永遠不過期。
- 加互斥鎖,避免多個線程同時訪問數據庫。
- 做二級緩存,或者雙緩存策略,采用不同的過期時間做雙層緩存。
緩存雪崩
緩存雪崩是指在我們設置緩存時采用了相同的過期時間,導致多個key的緩存在某一時刻同時失效,請求全部轉發到DB,DB瞬時壓力過重雪崩。
解決方案
緩存失效時的雪崩效應對底層系統的沖擊非常可怕。大多數系統設計者考慮用加鎖或者隊列的方式保證緩存的單線程(進程)寫,從而避免失效時大量的並發請求落到底層存儲系統上。這裏分享一個簡單方案就時講緩存失效時間分散開,比如我們可以在原有的失效時間基礎上增加一個隨機值,比如1-5分鐘隨機,這樣每一個緩存的過期時間的重復率就會降低,就很難引發集體失效的事件。
關鍵字: 時間岔開,確保大部分的key不會落在同一個expire點上。
也可以預熱緩存,在即將發生大並發訪問前手動觸發加載緩存不同的key,設置不同的過期時間,讓緩存失效的時間點盡量均勻
當然應對緩存擊穿的二級緩存策略以及永遠不過期策略也適用於緩存雪崩的場景
redis緩存穿透、緩存擊穿、緩存雪崩