redis緩存恢復-2022新項目

一、業務場景

  Web項目開發中,為了加快數據處理的的效率,大量的使用了各種緩存,緩存技術主要使用的是redis。導致出現的小小的

問題是redis緩存形成了一個比較強的依賴,並且有的數據暫時是沒有同步到業務數據庫當中進行存儲的,有不少數據都是直

接從緩存中獲取。這種處理方式確實加快了數據的處理效率,可是也存在一些問題。

二、需求分析

  當前由於系統要進行遷移,以前保存在一台服務器上面的redis中的數據,是不可能遷移的。即使運維人員願意遷移,操作起來

也是相當的麻煩。還有一個問題,如果發現緩存中的數據存在異常,如何使用某種機制去自動更新緩存或者是手動更新緩存數據,讓

緩存中的數據和數據庫中的最終趨於一致,並且保證數據的正確性呢?這就需要做緩存恢復。

三、解決方案

  緩存恢復只針對時效性比較長的數據,如果某些緩存數據幾分鐘更新一次,或者十幾分鐘更新一次,這種緩存數據就可以考慮不用

恢復。對於某些沒有失效時間限制的一些緩存數據,就需要做這種處理。需要使用的地方:一種情況是系統遷移的時候;一種情況是緩存

數據出現問題,需要採取某種措施更新緩存的時候。下面就來聊聊兩種緩存更新的方式。

.方式一:通過接口請求更新緩存.

這種方式比較常規,就是寫一個普通的接口,發一個請求到後台,傳遞對應的參數進行緩存更新操作。這種操作方式是立馬全量更新

所有的緩存數據。對於數據量不大的業務比較適合,更新的時間也不會太久,預估可能就一兩分鐘的樣子。可是當數據量很大的時候,

比如少說幾十萬甚至更多的數據都需要添加到緩存中,這種應該如何處理呢?

public boolean updateTest() {
Map<Integer, List<TransmitActivityTotal>> transmitActivityTotalMap = new HashMap<>(30);
List<TransmitActivityTotal> transmitActivityTotals = null;
StopWatch stopWatch = new StopWatch();
stopWatch.start();
try {
// 查詢數據
for(int i = 0; i < 30; i++){
// 根據不同的分表信息查詢不同的數據
transmitActivityTotals = null;
transmitActivityTotalMap.put(i, transmitActivityTotals);
}

// 處理數據
if (transmitActivityTotalMap.isEmpty()) {
return false;
}
Map<Long, Integer> idTotalMap = new HashMap<>();
Integer total = null;
for(Map.Entry<Integer, List<TransmitActivityTotal>> item : transmitActivityTotalMap.entrySet()) {
for(TransmitActivityTotal transmitActivityTotal : item.getValue()) {
total = transmitActivityTotal.getTotal() == null ? Integer.valueOf(0) : transmitActivityTotal.getTotal();
if (idTotalMap.keySet().contains(transmitActivityTotal.getId())) {
// 再次添加 原有數據 + 新數據
idTotalMap.put(transmitActivityTotal.getId(), idTotalMap.get(transmitActivityTotal.getId()) + total);
} else {
// 首次添加
idTotalMap.put(transmitActivityTotal.getId(), total);
}
}
}

for(Map.Entry<Long, Integer> item : idTotalMap.entrySet()) {
// 使用redis進行 恢復緩存 操作
log.info("id-->{}, 數量--->", item.getKey(), item.getValue());
}
stopWatch.stop();
log.info("緩存恢復耗時--->{}毫秒", stopWatch.getLastTaskTimeMillis());
return true;
} catch (Exception ex) {
stopWatch.stop();
log.error("緩存更新異常--->{}", ex);
return false;
}
}

方式二:通過數據字典表來控制緩存的更新。

自己目前所參與開發的項目,在項目啟動的時候,會將所有的數據字典信息添加到緩存當中,並且會隔幾分鐘去更新一次數據字典數據。

就是利用這一點來增量更新緩存信息,比如每次只更新某個用戶相關的操作數據,而不是一次性更新所有用戶的數據。減輕了服務器的壓力,

這種處理方式也更加的符合實際需求。舉一個簡單的示例,首先考慮兼容性問題,在設計的時候可以在數據字典中添加一個值,當這個值

OLD的時候,就使用舊有的邏輯,直接從緩存中獲取數據;如果是新系統,則可以在頁面中將這個數據字典表的值設置為NEW,這時就

使用新的邏輯,先從數據庫中去查詢數據,然後將查詢結果保存在緩存中。這樣設計就能夠兼容之前的系統,也可以進行系統的遷移。這裡

還存在一個問題,就是使用新系統時,不可能每次都去查詢數據庫,然後將數據存入緩存中。這時就可以添加第二個數據字典值,稱它為數

據版本吧,比如設置為100,也是先從緩存中獲取這個數據字典值a,然後從緩存中獲取獲取數據版本值b,判斷值a和值b是否一致。一致

則直接返回緩存數據。不一致則查詢數據庫,然後更新緩存,並且將緩存中的數據版本的值更新為數據字典的值。這樣在後台管理系統中,

更新數據版本的值,就可以動態的更新緩存數據的值,並且每次更新的緩存數據量很少。

這種設計稍微有些複雜,還是需要好好理解,自己最開始的時候也是沒有理解這種緩存恢復的方式。去詢問負責人之後,才搞清楚是如何

進行設計的。明白之後才開始寫代碼,最後進行測試,測試結論通過。