Caffeine缓存框架简介
Caffeine是一个高性能的Java缓存库,它基于Java 8及以上版本构建,提供了丰富的特性和灵活的配置选项,以支持各种复杂的缓存需求。在本教程中,我们将详细介绍Caffeine的使用方法和最佳实践,帮助您在实际项目中高效地使用Caffeine。
为什么选择Caffeine?
选择Caffeine作为缓存解决方案的理由有很多,以下是一些关键点:
-
强大的过期策略:
- 与谷歌提供的ConcurrentLinkedHashMap相比,Caffeine提供了多种基于时间的淘汰机制。这意味着您可以根据实际需求,设置缓存数据的自动过期时间,无论是基于数据的访问时间、写入时间还是自定义的时间规则。
-
高命中率:
- Caffeine采用了Window TinyLfu( Least Frequently Used)算法来自动调整缓存的大小,以实现接近最佳的命中率。这一特性使得Caffeine在许多场景下比传统的Guava Cache更加高效。
-
Spring框架推荐:
- 从Spring Framework 5.0(Spring Boot 2.0)开始,Spring官方推荐使用Caffeine作为缓存解决方案,取代了之前的Guava Cache。
Caffeine的主要特点
Caffeine的以下特点使其成为现代Java应用的理想缓存库:
-
基于Java 8的高性能缓存库:Caffeine利用Java 8的新特性,如Lambda表达式和Stream API,提供了高性能的缓存操作。
-
灵活的缓存构建:Caffeine提供了多种灵活的构造方法,允许开发者创建具有不同特性的本地缓存,例如自动加载数据、基于数量和失效时间的剔除策略、异步刷新等。
-
丰富的特性:
- 数据剔除提醒:Caffeine允许您在数据被淘汰时接收通知,这使得您可以在数据被移除前执行一些操作,如数据持久化。
- 写入广播机制:Caffeine支持在数据写入时触发事件,这有助于实现复杂的业务逻辑。
- 缓存访问统计:Caffeine提供了缓存访问的统计信息,帮助您监控和优化缓存性能。
通过本教程,您将学习如何利用Caffeine的这些特性,构建高效、可扩展的缓存解决方案,以满足您的业务需求。
缓存策略
Caffeine支持多种缓存策略,以下是一些主要的策略:
最大容量(Maximum Size)
限制缓存中可以存储的最大条目数。当达到这个上限时,缓存会根据其淘汰算法自动移除一些条目。
Cache<String, String> cache = Caffeine.newBuilder()
.maximumSize(100)
.build();
基于时间的过期策略
访问后过期(Expire After Access)
指定一个时间间隔,在该时间内如果没有访问某个缓存项,则认为它已过期,并在下次尝试访问时将其移除。
Cache<String, String> cache = Caffeine.newBuilder()
.expireAfterAccess(10, TimeUnit.MINUTES)
.build();
写入后过期(Expire After Write)
指定一个时间间隔,从写入(创建或更新)缓存项开始计时,超过该时间间隔后认为它已过期。
Cache<String, String> cache = Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.HOURS)
.build();
基于频率的淘汰策略
最近最少使用(LRU)
保留最近使用的条目,而移除最久未使用的条目。
最不经常使用(LFU)
保留最常使用的条目,而移除使用频率最低的条目。
Cache<String, String> cache = Caffeine.newBuilder()
.maximumSize(100)
.expireAfterAccess(10, TimeUnit.MINUTES)
.build();
自动刷新(Refresh After Write)
允许你定义一个时间间隔,当超过这个时间间隔时,即使缓存项没有过期,也会尝试重新加载数据。
LoadingCache<String, String> loadingCache = Caffeine.newBuilder()
.refreshAfterWrite(1, TimeUnit.HOURS)
.build(key -> fetchDataFromDatabase(key));
权重(Weigher)
允许每个缓存条目具有不同的权重,这对于存储大小各异的对象特别有用。
Cache<String, byte[]> cache = Caffeine.newBuilder()
.maximumWeight(1_000_000)
.weigher((Weigher<String, byte[]>) (key, value) -> value.length)
.build();
加载器
Caffeine提供了同步和异步两种加载器,用于在缓存中没有找到指定的键时自动加载数据。
同步加载器(Synchronous Loader)
LoadingCache<String, String> cache = Caffeine.newBuilder()
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
return fetchDataFromDatabase(key);
}
});
异步加载器(Asynchronous Loader)
AsyncLoadingCache<String, String> asyncCache = Caffeine.newBuilder()
.buildAsync(new AsyncCacheLoader<String, String>() {
@Override
public CompletableFuture<String> asyncLoad(String key, Executor executor) {
return CompletableFuture.supplyAsync(() -> fetchDataFromDatabase(key), executor);
}
});
异步缓存(Asynchronous Cache)
异步缓存允许以非阻塞的方式从缓存中获取数据。
AsyncLoadingCache<String, String> asyncCache = Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.buildAsync((key, executor) -> CompletableFuture.supplyAsync(() -> fetchDataFromDatabase(key), executor));
刷新策略(Refresh Policy)
刷新策略用于在缓存项仍然有效的情况下主动更新其值。
LoadingCache<String, String> cache = Caffeine.newBuilder()
.refreshAfterWrite(1, TimeUnit.HOURS)
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
return fetchDataFromDatabase(key);
}
});
统计信息(Statistics)
Caffeine允许你收集缓存操作的统计信息。
LoadingCache<String, String> cache = Caffeine.newBuilder()
.maximumSize(100)
.expireAfterWrite(10, TimeUnit.MINUTES)
.recordStats()
.build(key -> fetchDataFromDatabase(key));
CacheStats stats = cache.stats();
System.out.println("Hit count: " + stats.hitCount());
回收(Eviction)
回收是指当缓存达到其容量限制或其他条件触发时,自动移除一些条目的过程。
Cache<String, String> cache = Caffeine.newBuilder()
.maximumSize(100)
.build();