Jetcache踩坑合集

Jetcache踩坑合集

记录个人在使用jetcache时遇到的一些问题以及相应的解决方案

·

1 min read

写在前面

本文主要是记录个人在使用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表达式,但是又没有完全支持。