写在前面
本文主要是记录个人在使用jetcache时遇到的一些问题以及相应的解决方案,次之是将这些问题和解决方案发布到互联网中希望能帮助到一些人,如果觉得文章写得还不错,可以点赞收藏以鼓励我继续更新博客,这将对我非常重要。
流水账子标题中重复带上jetcache关键字主要是为了提高搜索的准确性,本身文章上下文已足够表达含义,但是为了优化搜索情况特意加上的。
踩坑流水账
jetcache默认返回值为null时候,不会缓存
这个是jetcache的默认策略,我之所以遇到这个问题是我自己写的测试代码时直接返回了null,我误认为是我spring aop配置有问题,导致缓存没有生效,实则是jetcache默认策略。
在com.alicp.jetcache.anno.Cached
注解中有一个属性cacheNullValue
,默认值为false,表示不缓存空值。
jetcache不支持模糊清空缓存
这点其实在GitHub issue清单中有好几个issue 都是与这个问题相关的,如果你也是从Spring Cache转到jetcache,由于缺少模糊清空缓存,会导致整个系统原有的实现都必须调整。
这个特性主要影响到缓存的数据是一个列表或者是一整颗树的情况,当列表或树中部分值更新以后,这个列表的缓存或树的缓存没有办法更新。
jetcache多节点缓存清空需要先有@Cached注册
这个是jetcache比较新的特性了,利用了CacheMonitor
接口,并且在这个的基础上抽象了一个com.alicp.jetcache.support.BroadcastManager
支持了更多的中间件,并且对于循环通知的问题有一个很好的解决方案。
但是jetcache只考虑到了同一份代码多节点部署的情况,我的实际应用场景比这个更复杂一些。
private void processCacheMessage(CacheMessage cacheMessage) {
if (sourceId.equals(cacheMessage.getSourceId())) {
return;
}
Cache cache = cacheManager.getCache(cacheMessage.getArea(), cacheMessage.getCacheName());
if (cache == null) {
logger.warn("Cache instance not exists: {},{}", cacheMessage.getArea(), cacheMessage.getCacheName());
return; }
Cache absCache = CacheUtil.getAbstractCache(cache);
if (!(absCache instanceof MultiLevelCache)) {
logger.warn("Cache instance is not MultiLevelCache: {},{}", cacheMessage.getArea(), cacheMessage.getCacheName());
return; }
Cache[] caches = ((MultiLevelCache) absCache).caches();
Set<Object> keys = Stream.of(cacheMessage.getKeys()).collect(Collectors.toSet());
for (Cache c : caches) {
Cache localCache = CacheUtil.getAbstractCache(c);
if (localCache instanceof AbstractEmbeddedCache) {
((AbstractEmbeddedCache) localCache).__removeAll(keys);
} else {
break;
}
}
}
在这个方法中,是直接通过cacheManager
实例去获取的,
当然这个问题也很好解决,你可以把这个模块的代码抽取出来,新建maven的module即可解决。
又或是直接增加@Cached
注解声明即可。
jetcache的key必须是一个EL表达式的key,不能是固定字符串
不太确定是不是jetcache特意为之,但是在使用过程中稍微注意一下即可
jetcache在遇到参数是集合的时候,key不可以是EL表达式
在这个方法 中,你可以看到当@CacheInvalidate
中的multi
属性声明为true时,可以看到调用了一个toIterable
方法,而这个方法的实现则是
private static Iterable toIterable(Object obj) {
if (obj.getClass().isArray()) {
if (obj instanceof Object[]) {
return Arrays.asList((Object[]) obj);
} else {
List list = new ArrayList();
int len = Array.getLength(obj);
for (int i = 0; i < len; i++) {
list.add(Array.get(obj, i));
}
return list;
}
} else if (obj instanceof Iterable) {
return (Iterable) obj;
} else {
return null;
}
}
只能说jetcache支持了EL表达式,但是又没有完全支持。