本地缓存方案Guava Cache
Guava Cache 是 Google 的 Guava 库提供的一个高效内存缓存解决方案,适用于需要快速访问且不频繁变更的数据。
// 普通缓存
Cache<Key, Value> cache = CacheBuilder.newBuilder()
.maximumSize(1000) // 最大条目数
.expireAfterWrite(10, TimeUnit.MINUTES) // 写入后10分钟过期
.recordStats() // 开启统计
.build();
// 自动加载缓存(LoadingCache)
LoadingCache<Key, Value> loadingCache = CacheBuilder.newBuilder()
.maximumWeight(10_000)
.weigher((Key k, Value v) -> v.size()) // 按值大小计算权重
.build(new CacheLoader<Key, Value>() {
@Override
public Value load(Key key) throws Exception {
return loadDataFromDataSource(key); // 缺失时自动加载
}
});
2. 核心操作
// 手动放入缓存
cache.put(key, value);
// 获取缓存(缺失时返回null)
Value value = cache.getIfPresent(key);
// 获取并自动加载(LoadingCache)
Value value = loadingCache.get(key); // 若缺失,调用CacheLoader.load()
// 手动移除
cache.invalidate(key);
cache.invalidateAll(); // 清空所有缓存
3. 过期策略
- 时间驱动:
expireAfterWrite(duration)
:写入后指定时间过期。expireAfterAccess(duration)
:最后一次访问后指定时间过期。
- 容量驱动:
maximumSize(long)
:基于LRU策略淘汰条目。maximumWeight(long)
+weigher
:按条目权重计算总容量。
4. 自动加载(LoadingCache)
- 同步加载:通过
CacheLoader.load()
方法在缓存未命中时同步加载数据。 - 批量加载:重写
loadAll(Iterable<? extends K> keys)
提升多键加载效率。 - 异步刷新:使用
refreshAfterWrite(duration)
在后台异步刷新过期条目,避免阻塞读取。
5. 移除监听器(RemovalListener)
监听缓存条目被移除的事件,执行资源释放等操作:
RemovalListener<Key, Value> listener = notification -> {
if (notification.wasEvicted()) {
// 处理资源释放
}
};
Cache<Key, Value> cache = CacheBuilder.newBuilder()
.removalListener(listener)
.build();
6. 统计信息
通过 recordStats()
启用统计,获取命中率、加载时间等数据:
Cache<?, ?> cache = CacheBuilder.newBuilder().recordStats().build();
// ...
CacheStats stats = cache.stats();
double hitRate = stats.hitRate(); // 命中率
long missCount = stats.missCount(); // 未命中次数
7. 线程安全
Guava Cache 默认线程安全,支持高并发读写,无需额外同步。
8. 异常处理
CacheLoader
中抛出的异常会被封装为UncheckedExecutionException
。- 建议在
load
方法中捕获异常,或通过getUnchecked()
处理。
9. 使用场景
- 高频读取,低频变更:如配置信息、用户会话。
- 计算密集型数据:避免重复计算(如复杂查询结果)。
- 资源敏感场景:通过权重控制内存占用。
示例代码
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterAccess(5, TimeUnit.MINUTES)
.recordStats()
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) {
return fetchDataFromDB(key); // 缺失时从数据库加载
}
});
// 使用缓存
try {
String data = cache.get("user:123");
} catch (ExecutionException e) {
// 处理加载异常
}
// 手动刷新
cache.refresh("user:123");
通过合理配置策略,Guava Cache 能有效平衡内存使用与性能,是 Java 应用中轻量级缓存的优选方案。