首頁 > 軟體

基於Redis快取資料常見的三種問題及解決

2022-06-16 18:06:50

1.快取穿透

1.1 問題描述

快取穿透是在使用者端/瀏覽器端請求一個不存在的key,這個key在redis中不存在,在資料庫中也不存在資料來源,每次對此key的請求從快取獲取不到,就會請求資料來源。

如使用一個不存在的使用者id去存取使用者資訊,redis和資料庫中都沒有,多次進行請求可能會壓垮資料來源

1.2 解決方法

一個一定不存在快取及查詢不到的資料,由於快取是不命中時被動寫入的,快取不存在,出於容錯考慮,查詢不到的資料是不會快取在redis當中,這將導致每次請求不存在的資料都會請求資料庫,失去了快取的意義。

(1)如果一個查詢返回的資料為空(不管是資料是否不存在),我們仍然把這個空結果(null)進行快取,設定空結果的過期時間會很短,最長不超過五分鐘

(2)設定可存取的名單(白名單):使用bitmaps型別定義一個可以存取的名單,名單id作為bitmaps的偏移量,每次存取和bitmap裡面的id進行比較,如果存取id不在bitmaps裡面,進行攔截,不允許存取。

(3)採用布隆過濾器

(4)進行實時的資料監控,發現Redis在命中率急速降低時,排查存取物件和存取資料,設定黑名單。

2.快取擊穿

2.1 問題描述

當用戶請求一個存在的key的資料時,此時redis中該key的資料已經過時,此時若有大量並行請求發現快取過期都會請求資料來源載入資料並且快取到redis當中,這個時候大量的並行可能會把資料庫服務壓垮。

2.2 解決方法

key可能在某一個時間段被大量的請求,這個key的資料被稱為熱點資料,這個時候便要考慮“擊穿”問題。

(1)預先設定熱門資料:在redis高峰存取之前,把一些熱門資料提前存入到redis裡面,加大這些熱門資料key的時長

(2)實時調整:現場監控哪些資料熱門,實時調整key的過期時長

(3)使用鎖:

  • 就是在快取失效的時候(判斷拿出來的值為空),不是立即去load db。
  • 先使用快取工具的某些帶成功操作返回值的操作(比如Redis的SETNX)去set一個mutex key
  • 當操作返回成功時,再進行load db的操作,並回設快取,最後刪除mutex key;
  • 當操作返回失敗,證明有執行緒在load db,當前執行緒睡眠一段時間再重試整個get快取的方法。

3.快取雪崩

3.1 問題描述

可以對應的資料存在,但是key的資料已經過期(redis快取過期,會自動刪除此key),此時大量的並行請求存取不同的key,即同時大量的存取不同的key,此時key處於過期階段,便會請求資料庫,大量的並行請求會壓垮資料庫伺服器,這種情況被稱為快取雪崩,和快取擊穿的不同是前者是一個key。

3.2 解決方法

快取失效時的雪崩效應對底層系統的衝擊非常可怕!

(1) 構建多級快取架構:

  • nginx快取 + redis快取 +其他快取(ehcache等)

(2) 使用鎖或佇列:

  • 用加鎖或者佇列的方式保證來保證不會有大量的執行緒對資料庫一次性進行讀寫,從而避免失效時大量的並行請求落到底層儲存系統上。不適用高並行情況

(3) 設定過期標誌更新快取:

  • 記錄快取資料是否過期(設定提前量),如果過期會觸發通知另外的執行緒在後臺去更新實際key的快取。

(4) 將快取失效時間分散開:

  • 比如我們可以在原有的失效時間基礎上增加一個隨機值,比如1-5分鐘隨機,這樣每一個快取的過期時間的重複率就會降低,就很難引發集體失效的事件。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。 


IT145.com E-mail:sddin#qq.com