摘要: JetCache是由阿里巴巴开源的通用缓存访问框架,若是你对Spring Cache很熟悉的话,请必定花一点时间了解一下JetCache,它更好用。JetCache能够作相似Spring Cache的注解式缓存,支持TTL、多级缓存、分布式自动刷新,也提供相似JSR107规范的Cache API。git
JetCache是由阿里巴巴开源的通用缓存访问框架,若是你对Spring Cache很熟悉的话,请必定花一点时间了解一下JetCache,它更好用。github
JetCache提供的核心能力包括:json
咱们直接看代码,最简单的使用场景是这样的:缓存
public interface UserService { @Cached(expire = 3600, cacheType = CacheType.REMOTE) User getUserById(long userId); }
这和Spring Cache很像,不过@Cached注解原生支持了TTL(超时时间),cacheType有LOCAL/REMOTE/BOTH三种选择,
分别表明本地内存/远程Cache Server(例如Redis)/两级缓存,可根据状况选用,合理的使用LOCAL或BOTH类型能够下降Cache Server的压力以及咱们提供的服务的响应时间。服务器
再看个复杂点的例子:框架
public interface UserService { @Cached(name="userCache-", key="#userId", expire = 3600) User getUserById(long userId); @CacheUpdate(name="userCache-", key="#user.userId", value="#user") void updateUser(User user); @CacheInvalidate(name="userCache-", key="#userId") void deleteUser(long userId); }
第一个例子中咱们没有指定key,JetCache会根据参数自动生成,这个例子咱们指定了key,而且展现了缓存的更新和删除。异步
自动刷新是JetCache的大杀器:分布式
public interface SummaryService{ @Cached(expire = 3600, cacheType = CacheType.REMOTE) @CacheRefresh(refresh = 1800, stopRefreshAfterLastAccess = 3600, timeUnit = TimeUnit.SECONDS) BigDecimal salesVolumeSummary(int timeId, long catagoryId); }
cacheType为REMOTE或者BOTH的时候,刷新行为是全局惟一的,也就是说,即便应用服务器是一个集群,也不会出现多个服务器同时去刷新一个key的状况。
一个key的刷新任务,自该key首次被访问后初始化,若是该key长时间不被访问,在stopRefreshAfterLastAccess指定的时间后,相关的刷新任务就会被自动移除,这样就避免了浪费资源去进行没有意义的刷新。ui
加在方法上的注解毕竟不能提供最灵活的控制,因此JetCache提供了Cache API,使用起来就像Map同样:this
UserDO user = userCache.get(12345L); userCache.put(12345L, loadUserFromDataBase(12345L)); userCache.remove(12345L); userCache.computeIfAbsent(1234567L, (key) -> loadUserFromDataBase(1234567L));
实际上Cache API实现了jsr107规范Cache接口的部分方法,之后的大版本可能会完整实现。
Cache实例能够经过注解建立:
@CreateCache(expire = 100, cacheType = CacheType.BOTH, localLimit = 50) private Cache<Long, UserDO> userCache;
也能够经过和guava cache/caffeine相似的builder来建立:
GenericObjectPoolConfig pc = new GenericObjectPoolConfig(); pc.setMinIdle(2); pc.setMaxIdle(10); pc.setMaxTotal(10); JedisPool pool = new JedisPool(pc, "localhost", 6379); Cache<Long, UserDO> userCache = RedisCacheBuilder.createRedisCacheBuilder() .keyConvertor(FastjsonKeyConvertor.INSTANCE) .valueEncoder(JavaValueEncoder.INSTANCE) .valueDecoder(JavaValueDecoder.INSTANCE) .jedisPool(pool) .keyPrefix("userCache-") .expireAfterWrite(200, TimeUnit.SECONDS) .buildCache();
Cache接口支持异步:
CacheGetResult r = cache.GET(userId); CompletionStage<ResultData> future = r.future(); future.thenRun(() -> { if(r.isSuccess()){ System.out.println(r.getValue()); } });
能够实现不严格的分布式锁:
cache.tryLockAndRun("key", 60, TimeUnit.SECONDS, () -> heavyDatabaseOperation());
使用Cache API也能够作自动刷新哦:
@CreateCache @CacheRefresh(timeUnit = TimeUnit.MINUTES, refresh = 60) private Cache<String, Long> orderSumCache; @PostConstruct public void init(){ orderSumCache.config().setLoader(this::loadOrderSumFromDatabase); }
若是没有使用注解,用builder同样也能够作出自动刷新:
Cache<String, Long> orderSumCache = RedisCacheBuilder.createRedisCacheBuilder() ......省略 .refreshPolicy(RefreshPolicy.newPolicy(60, TimeUnit.SECONDS)) .loader(this::loadOrderSumFromDatabase) .buildCache();
当前支持的缓存系统包括如下4个,并且要支持一种新的缓存也是很是容易的:
使用JetCache的系统需求:
更多文档能够在github的wiki上找到。