對原有代碼進行升級改造或者組件替換時,一個基本原則是新老邏輯要一致。保證新舊邏輯最常用的手段肯定是線上流量驗證最爲穩妥,相同的入參,走完原組件邏輯之後,再走一遍新組件的邏輯,比較輸出是否一致。但是實際情況中會遇到一種情況,要被替換的組件中包含一些外部依賴,例如需要從Redis中查詢一些數據,從第三方介質獲取一些信息等,這樣可能由於兩次查詢的結果不一致導致最終新老組件對比的結果存在差異。針對這種情況,一種非常好的解決手段就是將當前請求依賴的外部數據通過緩存存起來,以保證新組件查詢的數據和舊組件查詢的數據一致。示例代碼如下:
/**
* 組件替換模板
* @param <T>
*/
public abstract class PluginReplaceTemplate<T> {
public abstract T queryBusiData();
/** 組件替換Guava隊列 */
private GuavaCache<T> pluginReplaceGuava;
public PluginReplaceTemplate() { }
public PluginReplaceTemplate(GuavaCache<T> pluginReplaceGuava) {
this.pluginReplaceGuava = pluginReplaceGuava;
}
/**
* @param guavaKey guava緩存Key
* @param newPluginFlag true代表新組件調用,false代表老組件調用
* @param isHitCompare 是否命中對比階段
* @return 數據
*/
public T query(String guavaKey, boolean newPluginFlag, boolean isHitCompare){
if (newPluginFlag){
// 新組件:對比階段查guava,對比結束後不再使用guava
if (isHitCompare){
return pluginReplaceGuava.get(guavaKey);
}else {
return queryBusiData();
}
} else {
// 老組件:始終不使用guava數據,對比階段需要寫guava
T data = queryBusiData();
if (isHitCompare){
try {
pluginReplaceGuava.put(guavaKey, data);
} catch (Exception e) {
LogUtils.error(LogUtils.FILE_EXCEPTION, "PluginReplaceTemplate.put Data to Guava Exception", e);
}
}
return data;
}
}
}