當前位置: 妍妍網 > 碼農

Redis 有幾種緩存讀寫策略?

2024-03-23碼農

引言:在某一天面試的時候,小 x 被問到 Redis 三種緩存讀寫的策略,他懵了,原因是簡歷上明明是寫著熟悉 Redis,因此面試官可以隨意向任何一個方向進行開火,大家要註意從小點切入,除非自己是完全能夠掌握這門技術的,本文將帶你去了解三種常用的緩存讀寫策略的優缺點和使用場景。

題目

Redis 三種高效緩存讀寫策略你了解嗎?

推薦解析

旁路緩存模式(Cache Aside Pattern)

旁路緩存是最常見的緩存讀寫模式,適用於讀多寫少的使用經常。伺服端以資料庫比如 MySQL 為主,Redis 為輔,進行儲存。

寫操作流程

1)先更新資料庫

2)刪除 Redis 中的緩存

讀操作流程

1)嘗試從緩存中讀取數據,讀取到數據就直接返回

2)緩存中讀取不到,從資料庫中讀取數據

3)讀取完畢後,將數據放入緩存

緩存不一致可能的場景(先刪後更)

假如先刪除緩存,再更新資料庫,大機率會造成緩存不一致。執行緒 1 把 Redis 中 x 數據刪除,此時執行緒 2 發現緩存中沒有數據,從資料庫讀取,而執行緒以此時又把資料庫中的 x 數據更新,因此執行緒 2 讀取到的就是舊數據,造成了緩存不一致的情況。

緩存不一致發生機率小

被推薦的作法,就是上文講過的,先更新資料庫,再刪除緩存。

可能不一致的場景如下

1)緩存中 X(數據) 不存在(資料庫 X = 1) 2)執行緒 1 讀取資料庫,得到舊值(X = 1) 3)執行緒 2 更新資料庫(X = 2) 4)執行緒 2 刪除緩存 5)執行緒 1 將舊值寫入緩存(X = 1) 6)最終 X 的值在緩存中是 1(舊值),在資料庫中是 2(新值),也發生不一致。

此場景需要滿足:1)緩存失效 2) 讀寫請求同步對一個數據進行並行操作 3)更新資料庫+刪除緩存的時間大於讀取和寫入緩存的時間,也就是說寫操作時間大於度操作時間,因為緩存這塊可以不計入,理論發生機率是很小的。

旁路緩存優缺點

優點

1)提高數據存取速度

2)減少主記憶體存取

3)提高並行性

缺點

1)存在緩存資料庫不一致情況

2)首次請求數據一定不在緩存(可以緩存預熱結合定時任務)

3)寫操作頻繁會導致緩存被頻繁刪除,影響緩存命中率。(可以加分布式鎖,保證更新資料庫同時更新緩存。或者直接設定一個較短的過期時間)

旁路緩存範例程式碼

import java.util.HashMap;
import java.util.Map;
public classCacheAsideExample{
// 模擬緩存
privatestatic Map<String, String> cache = new HashMap<>();
// 模擬資料庫或資料來源
privatestatic Map<String, String> dataSource = new HashMap<>();
// 從緩存中獲取數據
publicstatic String getDataFromCache(String key){
return cache.get(key);
}
// 從資料來源中獲取數據
publicstatic String getDataFromDataSource(String key){
return dataSource.get(key);
}
// 將數據存入緩存
publicstaticvoidputDataIntoCache(String key, String value){
cache.put(key, value);
}
// 刪除緩存中的數據
publicstaticvoiddeleteDataFromCache(String key){
cache.remove(key);
}
// 從資料來源中載入數據,並存入緩存
publicstatic String loadData(String key){
String data = getDataFromDataSource(key);
if (data != null) {
putDataIntoCache(key, data);
}
return data;
}
publicstaticvoidmain(String[] args){
// 設定資料來源
dataSource.put("key1""value1");
dataSource.put("key2""value2");
// 從緩存中獲取數據,如果不存在則從資料來源中載入
String data1 = getDataFromCache("key1");
if (data1 == null) {
data1 = loadData("key1");
}
System.out.println("Data1: " + data1);
// 從緩存中獲取數據,如果不存在則從資料來源中載入
String data2 = getDataFromCache("key2");
if (data2 == null) {
data2 = loadData("key2");
}
System.out.println("Data2: " + data2);
// 刪除緩存中的數據
deleteDataFromCache("key1");
// 從緩存中獲取數據,如果不存在則從資料來源中載入
String data3 = getDataFromCache("key1");
if (data3 == null) {
data3 = loadData("key1");
}
System.out.println("Data3: " + data3);
}
}










讀寫穿透(Read/Write Through Pattern)

讀寫穿透策略將 Redis/Memcached 視為數據儲存的主要地方,也就是說將緩存充當原本的資料庫,利用 Cache 服務負責將數據讀取並寫入資料庫(MySQL、Oracle等)。

寫操作流程

1)先查詢緩存,緩存不存在,更新資料庫

2)緩存存在,先更新緩存,利用 Cache 服務同步更新資料庫。

讀操作流程

1)從緩存讀取數據,讀取到返回

2)緩存讀取不到,從資料庫載入後寫入緩存並返回。

和旁路緩存相反,讀寫穿透,主緩存從資料庫。

異步緩存寫入(Write Behind Pattern)

只更新緩存,不利用 Cache 服務更新資料庫,可以利用訊息佇列,先存放要消費的資訊,然後可以異步批次的更新資料庫,一般不使用,但資料庫的緩沖池機制是這種策略的一個實作,

適用場景:數據經常變化,一致性要求不高(可以延時同步),比如 PV、UV、點贊量。

其他補充

魚聰明 AI 的回答:

魚聰明 AI 地址:https://www.yucongming.com/

1) 旁路緩存(Cache Aside)

1.1)優點

  • 簡單易實作,適用於小規模系統。

  • 緩存數據不會過期,不會出現緩存雪崩。

  • 1.2)缺點

  • 數據一致性問題,需要應用程式主動更新緩存。

  • 緩存數據可能過期,導致緩存擊穿。

  • 1.3)使用場景

  • 適用於讀多寫少的場景。

  • 數據更新頻率不高,對數據即時性要求不高的場景。

  • 2) 讀寫穿透(Cache Through)

    2.1)優點

  • 數據一致性較好,不會出現數據不一致的情況。

  • 緩存數據不會過期,不會出現緩存雪崩。

  • 2.2)缺點

  • 需要保證資料來源的可靠性和效能。

  • 對於大規模系統,可能增加資料來源的壓力。

  • 2.3)使用場景

  • 適用於資料來源更新頻率高,對數據即時性要求高的場景。

  • 資料來源具有較好的效能和可靠性。

  • 3) 異步緩存寫入(Write Behind)

    3.1)優點

  • 減少對資料來源的頻繁寫入,提高效能。

  • 可以緩解瞬時寫入壓力,提高系統穩定性。

  • 3.2)缺點

  • 數據一致性可能受影響,存在一定的數據遺失風險。

  • 需要額外的機制來處理數據更新失敗的情況。

  • 3.3)使用場景

  • 適用於寫入頻率高,對數據即時性要求不高的場景。

  • 對數據遺失一定容忍度的場景。

  • 在實際套用中,根據系統的特點和需求,可以選擇合適的緩存讀寫策略來提高系統效能和穩定性。

    歡迎交流

    在閱讀完本篇文章後,你應該對 Redis 的三種緩存讀寫策略有了一定了解,一般采用第一個策略進行讀寫,其他兩種策略了解即可,在文末有三個問題將會檢驗本章的學習,歡迎在評論區發表意見。

    1)旁路緩存策略中,如何解決緩存數據過期和緩存擊穿的問題?

    2)讀寫穿透策略中,如何確保資料來源的可靠性和效能,以及如何處理資料來源故障的情況?

    3)在實際套用中,如何選擇合適的緩存讀寫策略,考慮到系統的特點和需求?

    點燃求職熱情!每周持續更新,海量面試題等你挑戰!趕緊關註面試鴨公眾號,輕松備戰春招和暑期實習!