一. 添加依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.1-jre</version>
</dependency>
二. 创建CacheLoader
LoadingCache<Long, String> cache = CacheBuilder.newBuilder()
//缓存池大小,在缓存项接近该大小时, Guava开始回收旧的缓存项
.maximumSize(GUAVA_CACHE_SIZE)
//设置过期策略
.expireAfterWrite(10, TimeUnit.MINUTES)
//设置刷新策略
.refreshAfterWrite(10, TimeUnit.MINUTES)
//移除监听器,缓存项被移除时会触发
.removalListener(new RemovalListener <Long, String>() {
@Override
public void onRemoval(RemovalNotification<Long, String> rn) {
//执行逻辑操作
}
})
//开启Guava Cache的统计功能
.recordStats()
.build(cacheLoader);
CacheLoader<String, String> cacheLoader = new CacheLoader<String, String>() {
//expire后或第一次加载时 调用
@Override
public String load(String key) throws Exception {
return "";
}
//refresh时调用
@Nullable
@Override
public ListenableFuture<String> reload(String key, HostInfo oldValue) throws Exception {
return super.reload(key, oldValue);
}
};
三.配置
1.expireAfterAccess(long, TimeUnit)
缓存项在给定时间内没有被读/写访问,则回收。请注意这种缓存的回收顺序和基于大小回收一样,再次加载key,调用CacheLoader的load方法。
2.expireAfterWrite(long, TimeUnit)
缓存项在给定时间内没有被写访问(创建或覆盖),则回收。如果认为缓存数据总是在固定时候后变得陈旧不可用,这种回收方式是可取的,再次加载key,调用CacheLoader的load方法。
3.refreshAfterAccess(long duration, TimeUnit unit)
缓存项在给定时间内没有被读/写访问,则刷新,再次加载key,调用CacheLoader的reload方法。
4.refreshAfterWrite(long duration, TimeUnit unit)
缓存项在给定时间内没有被写访问(创建或覆盖),则刷新,再次加载key,调用CacheLoader的reload方法。
因为load是同步加载,reload是异步加载。
expire load的优点:失效后下次查询是实时的数据。
缺点:如果大量缓存同时失效,查询耗时会比较长。
refresh reload的优点:reload是异步的,查询会很快返回。
缺点:当数据到达失效时间时,会先返回上次的value,当reload完成后再会返回实时的数据,数据实时性低于load。
综合使用
CacheBuilder.newBuilder().expireAfterWrite(timeOut, TimeUnit.MINUTES).expireAfterWrite(timeOut+ expireTime, TimeUnit.MINUTES);
在timeOut
内访问数据会使用reload加载数据,在超过timeOut+ expireTime
内访问数据会使用load加载数据。
四.Caffeine
https://www.oschina.net/p/ben-manes-caffeine?hmsr=aladdin1e1
Caffeine 是基于Java 8的高性能,接近最佳的缓存库。 Caffeine使用Google Guava启发的API提供内存缓存。
性能上优于Guava Cache,使用方法类似。