题要
新接到一个新的需求,由于订单系统的查询量和访问量比较巨大兼中航信高昂的查询费用,数据中台采用缓存查询结果来消峰和降低成本。最开始的项目中采用的是redis集群的形式,后由于访问过于频繁不得不采用cache+redis双重形式。
解决方案
java8更新后方法(函数)可以作为参数进行传递,借以下代码可以深入理解
import com.alicp.jetcache.embedded.CaffeineCacheBuilder;
//初始化cache对象
private Cache<String, Object> cache = CaffeineCacheBuilder.createCaffeineCacheBuilder()
.limit(Integer.MAX_VALUE)
.expireAfterWrite(5,TimeUnit.MINUTES)
.buildCache();
//获取和增加key
public <U, T> T getCacheValue(String key, Function<U, T> getValueFromDBFunc, U param, CacheExpirationTypes cacheExpirationType, short times, String regionName) {
String cacheKey = getKey(key,regionName);
Function<String, Object> func = (String k) -> (Object) getValueFromDBFunc.apply(param);
long expire = times;
TimeUnit timeUnit = TimeUnit.MINUTES;
switch (cacheExpirationType) {
case MINUTE:
timeUnit = TimeUnit.MINUTES;
break;
case HOURS:
timeUnit = TimeUnit.HOURS;
break;
case TODAY:
expire = todayAbsoluteExpiration();
timeUnit = TimeUnit.MILLISECONDS;
break;
}
return (T) cache.computeIfAbsent(cacheKey, func, true, expire, timeUnit);
}
//删除key
public boolean remove(String key, String regionName) {
return cache.remove(getKey(key,regionName));
}
//拼接key
private String getKey(String key,String regionName) {
return Strings.isNullOrEmpty(regionName) ? String.format("^T_%s__%s", DateTime.now().toString("yyyyMMdd"), key) : String.format("^T_%s_%s_%s", DateTime.now().toString("yyyyMMdd"), regionName, key);
}
以上代码为公司大神封装的一个cache读取的工具类,传统实现这个业务逻辑,需要第一先去cache中通过key获取想要获取的结果,if判断如果没有命中的情况下,在进入数据库或redis等其他持久数据源中获取数据,并将数据写入cache。其中最有意思的方法是getCacheValue()
。
这个方法中有一个参数为Function<U, T> getValueFromDBFunc
这个参数就是java8新增加的将方法(函数)作为参数进行传递,详细请看下图。
总的来说,用之前先评估一下qps和报文数据量。数据量较大的时候可能导致能存占用过大,所以大项目慎用。毕竟要在速度和质量中寻找平衡。
使用前:
使用后:
嗯!当然这是本机测试…
列出一些参考: