兜底是服務高可用的有效手段之一,一般用於對業務要求較高,服務可用性較強的場景
兜底常用的手段有:try catch捕獲異常指定兜底邏輯;默認值兜底;緩存崩潰數據庫兜底等等
接下來介紹另一場兜底策略:副本兜底,被用在我們服務的核心鏈路上。
副本兜底
什麼叫副本兜底呢,就是記錄接口不同請求參數情況下,各自的最近的一次返回值,有且只記錄最近的一次返回值。如果接口異常,直接返回對應請求參數的最近一次返回值。但是不可能記錄所有參數的返回值,只記錄熱點參數的返回值,非熱點參數執行接口的頻率很低,允許少量的失敗,這裏就需要用到lru淘汰算法,淘汰非熱點數據,保留熱點數據。
代碼實現
這裏用到guava的本地緩存工具包,自帶lru淘汰算法
public class LocalTest {
//guava本地緩存,只存儲1000條緩存,非熱點緩存自動淘汰,12小時都未更新的緩存也會自動過期
private static final LoadingCache<Integer, Optional<Object>> CACHE
= CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(12, TimeUnit.HOURS)
.build(new CacheLoader<Integer, Optional<Object>>() {
@Override
public Optional<Object> load(Integer key) {
return Optional.fromNullable(null);
}
});
public Object core(int shopId) {
try {
//do some thing
//do some thing
//do some thing
//返回結果Object
//存儲返回的結果
CACHE.put(shopId, Optional.fromNullable(new Object()));
} catch (Exception e) {
//異常後從本地緩存裏取存儲的最近一次返回記錄
return CACHE.getUnchecked(shopId).orNull();
}
return new Object();
}
}