Cache
高性能java缓存库-Caffeine
Caffeine简介
Caffeine基于java8的高性能,接近最优的缓存库。Caffeine提供的内存缓存使用参考Google guava的API。Caffeine是基于Google guava和 ConcurrentLinkedHashMap的设计经验上改进的成果。
Caffeine可以通过建造者模式灵活的组合以下特性:
通过异步自动加载实体到缓存中
基于大小的回收策略
基于时间的回收策略
自动刷新
key自动封装虚引用
value自动封装弱引用或软引用
实体过期或被删除的通知
写入外部资源
统计累计访问缓存
加载策略
Caffeine提供了3种加载策略:手动加载,同步加载,异步加载
手动加载
1 | Cache<Key, Graph> cache = Caffeine.newBuilder() |
同步加载
构造Cache时候,build方法传入一个CacheLoader实现类。实现load方法,通过key加载value。
1 | LoadingCache<Key, Graph> cache = Caffeine.newBuilder() |
AsyncLoadingCache 是 LoadingCache 的变体, 可以异步计算实体在一个线程池(Executor)上并且返回 CompletableFuture.
回收策略
Caffeine提供了3种回收策略:基于大小回收,基于时间回收,基于引用回收
基于大小回收
// 基于实体数量淘汰实体
1 | LoadingCache<Key, Graph> graphs = Caffeine.newBuilder() |
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.maximumWeight(10_000)
.weigher((Key key, Graph graph) -> graph.vertices().size())
.build(key -> createExpensiveGraph(key));
1 |
|
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.expireAfterAccess(5, TimeUnit.MINUTES)
.build(key -> createExpensiveGraph(key));
1 | 基于写之后,在实体被写入后的一段时间后过期 |
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(key -> createExpensiveGraph(key));
1 | 自定义策略Expiry,可以自定义在实体被读,被更新,被创建后的时间过期。 |
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.expireAfter(new Expiry<Key, Graph>() {
public long expireAfterCreate(Key key, Graph graph, long currentTime) {
// Use wall clock time, rather than nanotime, if from an external resource
long seconds = graph.creationDate().plusHours(5)
.minus(System.currentTimeMillis(), MILLIS)
.toEpochSecond();
return TimeUnit.SECONDS.toNanos(seconds);
}
public long expireAfterUpdate(Key key, Graph graph,
long currentTime, long currentDuration) {
return currentDuration;
}
public long expireAfterRead(Key key, Graph graph,
long currentTime, long currentDuration) {
return currentDuration;
}
})
.build(key -> createExpensiveGraph(key));
1 |
|
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.weakKeys()
.weakValues()
.build(key -> createExpensiveGraph(key));
1 |
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.softValues()
.build(key -> createExpensiveGraph(key));
1 | #### 自动刷新 |
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.maximumSize(10_000)
.refreshAfterWrite(1, TimeUnit.MINUTES)
.build(key -> createExpensiveGraph(key));
1 | 在写后的持续时间过后,调用createExpensiveGraph刷新 |
Cache<Key, Graph> graphs = Caffeine.newBuilder()
.removalListener((Key key, Graph graph, RemovalCause cause) ->
System.out.printf(“Key %s was removed (%s)%n”, key, cause))
.build();
1 | 通过removalListener添加实体移除监听器 |
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.writer(new CacheWriter<Key, Graph>() {
@Override public void write(Key key, Graph graph) {
// 写入到外部存储或二级缓存
}
@Override public void delete(Key key, Graph graph, RemovalCause cause) {
// 删除外部存储或者二级缓存
}
})
.build(key -> createExpensiveGraph(key));
1 | 使用场景 |
Cache<Key, Graph> graphs = Caffeine.newBuilder()
.maximumSize(10_000)
.recordStats()
.build();
通过使用Caffeine.recordStats(), 可以转化成一个统计的集合. 通过 Cache.stats() 返回一个CacheStats。CacheStats提供以下统计方法
hitRate(): 返回缓存命中率
evictionCount(): 缓存回收数量
averageLoadPenalty(): 加载新值的平均时间