Java Caffeine 高性能缓存库详解与使用案例详解

 更新时间:2025年10月09日 10:59:58   作者:Lisonseekpan  
Caffeine是Java生态中最先进的本地缓存库,其 高性能、低延迟 的设计使其成为现代应用的首选,通过灵活的配置和强大的统计功能,开发者可以轻松实现高效的缓存策略,显著提升系统性能,本文介绍Java Caffeine高性能缓存库详解与使用案例,感兴趣的朋友一起看看吧

Java Caffeine 高性能缓存库详解与使用案例

一、Caffeine 简介

1.1 什么是 Caffeine?

Caffeine 是一个基于 Java 8 的高性能本地缓存库,由 Ben Manes 开发,旨在提供比 Guava Cache 更高效的缓存实现。其核心特性包括:

  • 基于大小的驱逐(Size-based Eviction)
  • 基于时间的过期(Time-based Expiry)
  • 弱引用/软引用支持
  • 统计功能(命中率、访问次数等)
  • 异步加载(Async Loading)

Caffeine 的设计目标是最小化延迟和内存占用,适用于需要高吞吐量和低延迟的场景(如 Web 应用、微服务)。

二、核心特性详解

2.1 缓存驱逐策略

2.1.1 基于大小的驱逐(Size-based Eviction)

Caffeine 使用 Window TinyLFU 算法,动态管理缓存大小,确保最常用的元素保留在缓存中。

Cache<String, String> cache = Caffeine.newBuilder()
.maximumSize(100)// 最大缓存大小为100
.build();
2.1.2 基于时间的过期
  • 基于访问时间(Access Time):元素在最后一次访问后过期。
  • 基于写入时间(Write Time):元素在插入后过期。
Cache<String, String> cache = Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)// 写入后10分钟过期
.expireAfterAccess(5, TimeUnit.MINUTES)// 最后一次访问后5分钟过期
.build();
2.1.3 弱引用/软引用
  • 弱引用(Weak Keys/Values):当 JVM 内存不足时自动回收。
  • 软引用(Soft Values):在 OOM(内存溢出)前回收。
Cache<String, String> cache = Caffeine.newBuilder()
.weakKeys()// 键使用弱引用
.softValues()// 值使用软引用
.build();

2.2 统计功能

Caffeine 提供详细的缓存统计信息,包括命中率、未命中次数、加载次数等。

Cache<String, String> cache = Caffeine.newBuilder()
.recordStats()// 启用统计
.maximumSize(100)
.build();
// 获取统计信息
CacheStats stats = cache.stats();
System.out.println("命中率: " + stats.hitRate());

2.3 异步加载(Async Loading)

通过 AsyncLoadingCache 实现异步缓存加载,避免阻塞主线程。

AsyncLoadingCache<String, String> asyncCache = Caffeine.newBuilder()
.maximumSize(100)
.buildAsync(key -> {
// 模拟耗时操作
return CompletableFuture.supplyAsync(() -> fetchFromDB(key));
});
// 获取缓存(异步)
CompletableFuture<String> future = asyncCache.get("key");

三、使用案例详解

3.1 单体应用缓存

场景:用户信息缓存
public class UserService {
private final Cache<String, User> userCache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
public User getUser(String userId) {
return userCache.get(userId, id -> fetchUserFromDB(id));
}
private User fetchUserFromDB(String id) {
// 模拟数据库查询
return new User(id, "User_" + id);
}
}
优势:
  • 减少数据库压力:高频查询直接命中缓存。
  • 动态刷新:Caffeine 自动管理缓存更新。

3.2 分布式系统中的缓存

场景:分布式缓存同步

Caffeine 本身是本地缓存,但可通过与 Redis 结合实现分布式缓存。

public class DistributedCache {
private final Cache<String, String> localCache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
public String get(String key) {
return localCache.get(key, k -> {
String value = fetchFromRedis(k);
if (value == null) {
value = fetchFromDB(k);
saveToRedis(k, value); // 写回 Redis
}
return value;
});
}
}
优势:
  • 本地缓存加速:减少对 Redis 的直接访问。
  • 降级容错:Redis 不可用时可直接访问数据库。

3.3 Spring Boot 集成

1. 添加依赖
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.8</version>
</dependency>
2. 配置缓存
@Configuration
public class CacheConfig {
@Bean
public Cache<String, String> myCache() {
return Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
}
}
3. 使用缓存
@Service
public class MyService {
@Autowired
private Cache<String, String> myCache;
public String getData(String key) {
return myCache.get(key, k -> fetchFromExternalService(k));
}
}

四、性能优化技巧

4.1 避免缓存雪崩

  • 随机过期时间:为缓存设置随机过期时间,避免大量缓存同时失效。
  • 热点数据预加载:对高频访问的数据主动加载到缓存。
// 随机过期时间
Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.scheduler(Scheduler.systemScheduler())
.build();

4.2 缓存命中率优化

  • 合理设置大小:根据业务访问模式调整 maximumSize
  • 监控统计:定期分析 hitRate()evictionCount(),调整策略。

4.3 内存管理

  • 软引用值(softValues):在 JVM 内存不足时自动回收缓存。
  • 定期清理:使用 cleanUp() 手动触发清理。
cache.cleanUp(); // 手动清理过期缓存

五、常见问题与解决方案

5.1 缓存穿透(Cache Penetration)

问题:查询不存在的数据导致频繁访问数据库。
解决方案

  • 布隆过滤器(Bloom Filter):拦截不存在的键。
  • 空值缓存:对查询结果为空的键设置短暂缓存。
String value = cache.get(key, k -> {
String result = fetchFromDB(k);
if (result == null) {
cache.put(k, "");// 缓存空值
}
return result;
});

5.2 缓存击穿(Cache Breakdown)

问题:热点数据过期后大量请求直接访问数据库。
解决方案

  • 互斥锁(Mutex Lock):仅允许一个线程重建缓存。
  • 永不过期:热点数据设置永不过期,定时异步更新。
String value = cache.get(key, k -> {
synchronized (lock) {
if (cache.getIfPresent(k) == null) {
String result = fetchFromDB(k);
cache.put(k, result);
return result;
}
}
return cache.getIfPresent(k);
});

5.3 缓存雪崩(Cache Avalanche)

问题:大量缓存同时失效,导致数据库压力激增。
解决方案

  • 随机过期时间:为缓存设置随机过期时间。
  • 分层缓存:本地缓存 + Redis 分布式缓存。

六、Caffeine 与 Guava Cache 对比

特性CaffeineGuava Cache
算法Window TinyLFU(高命中率)Window TinyLFU(与 Caffeine 相同)
异步加载支持(AsyncLoadingCache)不支持
统计功能详细统计(命中率、加载次数等)基本统计
性能更高吞吐量和更低延迟稍逊于 Caffeine
维护状态活跃维护已停止更新

七、总结

Caffeine 是 Java 生态中最先进的本地缓存库,其 高性能、低延迟 的设计使其成为现代应用的首选。通过灵活的配置和强大的统计功能,开发者可以轻松实现高效的缓存策略,显著提升系统性能。结合异步加载和分布式缓存方案,Caffeine 能够满足从单体应用到微服务架构的多样化需求。

八、参考资料

  • Caffeine 官方文档:https://github.com/ben-manes/caffeine
  • Java 缓存最佳实践:https://www.baeldung.com/java-cache-best-practices
  • Caffeine 与 Redis 集成示例:https://github.com/ben-manes/caffeine-spring-boot-starter

到此这篇关于Java Caffeine 高性能缓存库详解与使用案例的文章就介绍到这了,更多相关Java Caffeine 高性能缓存库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot中的五种对静态资源的映射规则的实现

    SpringBoot中的五种对静态资源的映射规则的实现

    这篇文章主要介绍了SpringBoot中的五种对静态资源的映射规则的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • Springboot jar文件如何打包zip在linux环境运行

    Springboot jar文件如何打包zip在linux环境运行

    这篇文章主要介绍了Springboot jar文件如何打包zip在linux环境运行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • java通过jni调用opencv处理图像的方法

    java通过jni调用opencv处理图像的方法

    今天小编就为大家分享一篇java通过jni调用opencv处理图像的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • 一篇文章教你如何用Java自定义一个参数校验器

    一篇文章教你如何用Java自定义一个参数校验器

    这篇文章主要介绍了使用java自定义一个参数校验器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习
    2021-09-09
  • 实例讲解分布式缓存软件Memcached的Java客户端使用

    实例讲解分布式缓存软件Memcached的Java客户端使用

    这篇文章主要介绍了分布式缓存软件Memcached的Java客户端使用,Memcached在GitHub上开源,作者用其Windows平台下的版本进行演示,需要的朋友可以参考下
    2016-01-01
  • maven多个plugin相同phase的执行顺序

    maven多个plugin相同phase的执行顺序

    这篇文章主要介绍了maven多个plugin相同phase的执行顺序,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • SpringBoot接口或方法进行失败重试的实现方式

    SpringBoot接口或方法进行失败重试的实现方式

    为了防止网络抖动,影响我们核心接口或方法的成功率,通常我们会对核心方法进行失败重试,如果我们自己通过for循环实现,会使代码显得比较臃肿,所以本文给大家介绍了SpringBoot接口或方法进行失败重试的实现方式,需要的朋友可以参考下
    2024-07-07
  • Java 使用IO流实现大文件的分割与合并实例详解

    Java 使用IO流实现大文件的分割与合并实例详解

    这篇文章主要介绍了Java 使用IO流实现大文件的分割与合并实例详解的相关资料,需要的朋友可以参考下
    2016-12-12
  • SpringDataJpa写原生sql遇到的问题及解决

    SpringDataJpa写原生sql遇到的问题及解决

    这篇文章主要介绍了SpringDataJpa写原生sql遇到的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • 浅析scala中map与flatMap的区别

    浅析scala中map与flatMap的区别

    这篇文章主要介绍了浅析scala中map与flatMap的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-06-06

最新评论