一 介紹
在高并發的場景之下,Hystrix中提供了請求緩存的功能,可以友善地開啟和使用請求緩存來優化系統,達到減輕高并發時請求線程的消耗、降低請求響應時間的效果。
二開啟請求緩存功能
在實作HystrixCommand或HystrixObservableCommand時,通過重載getCacheKey()方法來開啟請求緩存。
例如:
public class CommandUsingRequestCache extends HystrixCommand<Boolean> {
private final int value;
protected CommandUsingRequestCache(int value) {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
this.value = value;
}
@Override
protected Boolean run() {
return value == 0 || value % 2 == 0;
}
//通過getCacheKey方法中傳回的請求緩存key值,就能讓該請求指令具備緩存功能。此時當不同的外部請求
//處理邏輯調用了同一個依賴服務時,Hystrix會根據getCacheKey方法傳回的值區分是否是重複請求,
//如果它們的cachekey相同時候,那麼該依賴服務值會在第一個請求達到時被真實的調用一次,另外一個
//請求則直接從請求緩存中傳回結果,是以開啟緩存有以下好處:
//減少重複請求數,降低依賴服務的并發度
//在同一使用者請求的上下文中,相同依賴服務的傳回資料始終保持一緻。
//請求緩存在run()和construct()執行之前生效,是以可以有效減少不必要的線程開銷。
@Override
protected String getCacheKey() {
return String.valueOf(value);
}
}
三 清理失效緩存功能
使用請求緩存時,如果隻是讀操作,那麼不需要考慮緩存内容是否正确的問題,但是如果請求指令中還有更新資料的操作,那麼緩存中的資料就需要我們在進行寫操作時進行及時處理,以防止讀操作的請求指令擷取到失效的資料。
在Hystrix中,可以通過HystrixRequestCache.clear()方法來進行緩存的清理。
//當我們對GetterCommand指令實作了請求緩存之後,那麼勢必需要為SetterCommand指令實作清理緩存,以保證
//prefixStoredOnRemoteDataStore被更新之後,Hystrix請求緩存中相同的緩存的結果被移除,這樣下一次根據id
//擷取prefixStoredOnRemoteDataStore時,不會從緩存去擷取資料
public class CommandUsingRequestCacheInvalidation {
/* represents a remote data store */
private static volatile String prefixStoredOnRemoteDataStore = "ValueBeforeSet_";
//根據id擷取資料
public static class GetterCommand extends HystrixCommand<String> {
private static final HystrixCommandKey GETTER_KEY = HystrixCommandKey.Factory.asKey("GetterCommand");
private final int id;
public GetterCommand(int id) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GetSetGet"))
.andCommandKey(GETTER_KEY));
this.id = id;
}
@Override
protected String run() {
return prefixStoredOnRemoteDataStore + id;
}
@Override
protected String getCacheKey() {
return String.valueOf(id);
}
//該方法從預設的Hystrix并發政策中根據GETTER_KEY擷取指令的請求緩存對象HystrixRequestCache的執行個體
//然後再調用該請求緩存對象的clear方法,對Key為id值的緩存内容進行清理。
public static void flushCache(int id) {
HystrixRequestCache.getInstance(GETTER_KEY,
HystrixConcurrencyStrategyDefault.getInstance()).clear(String.valueOf(id));
}
}
//用于更新prefixStoredOnRemoteDataStore的值
public static class SetterCommand extends HystrixCommand<Void> {
private final int id;
private final String prefix;
public SetterCommand(int id, String prefix) {
super(HystrixCommandGroupKey.Factory.asKey("GetSetGet"));
this.id = id;
this.prefix = prefix;
}
@Override
protected Void run() {
// persist the value against the datastore
prefixStoredOnRemoteDataStore = prefix;
//在調用了寫prefixStoredOnRemoteDataStore之後,增加了對GetterCommand
//中靜态方法flushCache的調用,以實作對時效緩存的清理工作。
GetterCommand.flushCache(id);
// no return value
return null;
}
}
}