一 介绍
在高并发的场景之下,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;
}
}
}