深度解析 Caffeine:高性能 Java 缓存库
1. Caffeine 简介
Caffeine 是一个基于 Java 8 的高性能本地缓存库,由 Ben Manes 开发,旨在替代 Google Guava Cache,提供更优的缓存策略、更高的吞吐量和更灵活的配置。
核心优势
✅ 卓越的性能:采用优化的数据结构(如 Window TinyLFU 淘汰算法),减少锁竞争,提升并发访问效率。
✅ 灵活的缓存策略:支持基于大小、时间、权重等多种淘汰机制。
✅ 丰富的功能:自动刷新、异步加载、批量操作等高级特性。
✅ 无缝集成 Spring:与 Spring Cache 完美结合,轻松替换 Redis 或 Ehcache。
2. Caffeine 核心机制
2.1 缓存淘汰策略
Caffeine 提供多种缓存淘汰策略,防止内存无限增长:
策略 | 方法 | 说明 |
---|---|---|
基于大小 | maximumSize(long) | 限制缓存最大条目数 |
基于权重 | maximumWeight(long) + weigher() | 根据条目权重限制缓存 |
基于时间 | expireAfterWrite / expireAfterAccess | 写入/访问后过期 |
手动淘汰 | invalidate(key) / invalidateAll() | 主动移除缓存 |
2.2 缓存加载方式
Caffeine 支持 同步加载 和 异步加载:
// 同步加载(阻塞)
LoadingCache<Key, Value> cache = Caffeine.newBuilder().build(key -> fetchFromDB(key));// 异步加载(非阻塞)
AsyncLoadingCache<Key, Value> asyncCache = Caffeine.newBuilder().buildAsync((key, executor) -> CompletableFuture.supplyAsync(() -> fetchFromDB(key), executor));
2.3 自动刷新机制
refreshAfterWrite
允许缓存条目在写入后一段时间自动刷新(异步,不阻塞请求):
LoadingCache<String, Data> cache = Caffeine.newBuilder().refreshAfterWrite(1, TimeUnit.MINUTES) // 1分钟后访问时触发刷新.build(this::loadDataFromDB);
注意:刷新时返回旧值,后台异步加载新值,适合高并发场景。
3. 代码实战:Caffeine + Spring Boot
3.1 基础配置
@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic Caffeine<Object, Object> caffeineConfig() {return Caffeine.newBuilder().maximumSize(1000) // 最大1000条.expireAfterWrite(10, TimeUnit.MINUTES) // 10分钟过期.refreshAfterWrite(1, TimeUnit.MINUTES); // 1分钟后自动刷新}@Beanpublic CacheManager cacheManager(Caffeine<Object, Object> caffeine) {CaffeineCacheManager cacheManager = new CaffeineCacheManager();cacheManager.setCaffeine(caffeine);return cacheManager;}
}
3.2 业务层使用
@Service
public class UserService {@Cacheable(value = "users", key = "#id") // 缓存名称为 "users"public User getUserById(Long id) {return userRepository.findById(id).orElse(null);}@CacheEvict(value = "users", key = "#id") // 删除缓存public void deleteUser(Long id) {userRepository.deleteById(id);}
}
4. 高级用法
4.1 多级缓存(Caffeine + Redis)
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory,Caffeine<Object, Object> caffeine
) {// 本地缓存CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();caffeineCacheManager.setCaffeine(caffeine);// Redis 缓存RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()).build();// 组合缓存(先查本地,再查Redis)return new CompositeCacheManager(caffeineCacheManager, redisCacheManager);
}
4.2 批量操作优化
public Map<Long, User> batchGetUsers(List<Long> userIds) {// 批量查询缓存Map<Long, User> cachedUsers = cache.getAll(userIds);// 查找未命中的IDList<Long> missingIds = userIds.stream().filter(id -> !cachedUsers.containsKey(id)).collect(Collectors.toList());if (!missingIds.isEmpty()) {// 从DB加载并更新缓存Map<Long, User> dbUsers = userRepository.batchFindByIds(missingIds);cache.putAll(dbUsers);cachedUsers.putAll(dbUsers);}return cachedUsers;
}
5. 注意事项 & 最佳实践
5.1 缓存穿透问题
问题:恶意请求不存在的 key,导致频繁查询数据库。
解决方案:
.build(key -> {User user = fetchFromDB(key);if (user == null) {return new NullValue(); // 缓存空对象}return user;
});
5.2 缓存雪崩
问题:大量缓存同时失效,导致数据库压力激增。
解决方案:
.expireAfterWrite(10 + ThreadLocalRandom.current().nextInt(5), TimeUnit.MINUTES) // 随机过期时间
5.3 内存监控
Caffeine 提供统计信息:
.recordStats() // 启用统计
CacheStats stats = cache.stats();
System.out.println("命中率: " + stats.hitRate());
System.out.println("加载次数: " + stats.loadCount());
5.4 最佳实践
✔ 合理设置缓存大小:避免 OOM(如 maximumSize(10000)
)。
✔ 结合 TTL + 自动刷新:保证数据新鲜,同时避免阻塞请求。
✔ 分布式环境使用多级缓存:本地缓存 + Redis,减少网络开销。
✔ 监控缓存命中率:优化缓存策略,避免缓存失效风暴。
6. 总结
Caffeine 是 Java 生态中最强大的本地缓存库之一,适用于:
- 高频访问的只读数据(如配置、用户信息)
- 高并发场景(如电商商品详情页)
- 计算成本高的操作(如复杂查询、API 调用)
通过合理的配置(refreshAfterWrite
+ expireAfterWrite
)和最佳实践(防穿透、防雪崩),可以极大提升系统性能。
推荐组合:
- 单机应用:纯 Caffeine
- 分布式系统:Caffeine + Redis(多级缓存)
附录:官方资源
- GitHub: Caffeine
- Spring Cache + Caffeine
希望这篇深度解析能帮助你掌握 Caffeine 的核心机制和最佳实践! 🚀