初识Caffeine

一、前言:为什么你需要 Caffeine?

你是否遇到过这些问题?

  • ❌ 频繁查询数据库,接口响应慢
  • ❌ 热点数据反复被请求,浪费资源
  • ❌ 手写 ConcurrentHashMap 缓存,结果内存爆炸(OOM)

Caffeine 是一个高性能、易用、现代化的 Java 本地缓存库 ,由 Guava Cache 的原作者打造,号称 "Guava Cache 的继任者"。

它能帮你:

✅ 微秒级数据访问 (比 Redis 快 1000 倍)

✅ 自动淘汰旧数据 ,防止内存溢出

✅ 一行代码实现缓存加载

本文将带你从零开始,快速上手 Caffeine!


二、Caffeine 是什么?

Caffeine 是一个基于 Java 8+ 的高性能进程内缓存库,特点如下:

特性 说明
高性能 采用 Window TinyLFU 淘汰算法,命中率更高
简单易用 API 与 Guava Cache 高度相似,学习成本低
功能丰富 支持自动过期、异步加载、统计监控等
社区活跃 Spring Boot 3.x 官方推荐本地缓存方案

💡 一句话理解 :Caffeine = 更快 + 更省内存 + 更智能 的 ConcurrentHashMap


三、快速入门:5 分钟上手 Caffeine

3.1 添加 Maven 依赖

XML 复制代码
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactityId>caffeine</artifactId>
    <version>3.1.8</version> <!-- 推荐使用最新版 -->
</dependency>

3.2 基础用法:手动存取

java 复制代码
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;

public class CaffeineDemo {
    public static void main(String[] args) {
        // 创建缓存:最多存 1000 个条目,写入 5 分钟后过期
        Cache<String, String> cache = Caffeine.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(5, TimeUnit.MINUTES)
            .build();

        // 存入数据
        cache.put("name", "Alice");

        // 读取数据
        String name = cache.getIfPresent("name");
        System.out.println(name); // 输出:Alice

        // 不存在时返回 null
        String notExist = cache.getIfPresent("age");
        System.out.println(notExist); // 输出:null
    }
}

四、高级用法:自动加载缓存(LoadingCache)

最强大的功能来了!当缓存未命中时,自动从数据源加载。

4.1 自动回源查询数据库

java 复制代码
LoadingCache<Long, User> userCache = Caffeine.newBuilder()
    .maximumSize(10_000)
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .build(key -> {
        // 模拟从数据库加载
        System.out.println("从数据库加载用户: " + key);
        return loadUserFromDB(key); // 你的 DAO 方法
    });

// 第一次调用:触发 loadUserFromDB
User user1 = userCache.get(1001L);

// 第二次调用:直接从缓存返回
User user2 = userCache.get(1001L);

✅ 效果:业务代码无需关心"先查缓存再查 DB"的逻辑,Caffeine 自动搞定!


五、核心配置详解

5.1 淘汰策略

配置 作用
.maximumSize(1000) 最多缓存 1000 个 key-value
.expireAfterWrite(5, MINUTES) 写入后 5 分钟过期
.expireAfterAccess(10, MINUTES) 最后访问后 10 分钟过期
.weakKeys() key 使用弱引用(GC 可回收)
.softValues() value 使用软引用(内存不足时回收)

⚠️ 注意 :maximumSize 和 weak/soft 不能同时使用。

5.2 异步加载(AsyncLoadingCache)

java 复制代码
AsyncLoadingCache<String, String> asyncCache = Caffeine.newBuilder()
    .buildAsync((key, executor) -> 
        CompletableFuture.supplyAsync(() -> fetchDataFromRemote(key))
    );

CompletableFuture<String> future = asyncCache.get("data");
String result = future.get(); // 阻塞等待结果

六、监控缓存性能

Caffeine 内置统计功能,轻松查看命中率:

java 复制代码
Cache<String, Object> cache = Caffeine.newBuilder()
    .recordStats() // 开启统计
    .build();

// ... 使用缓存 ...

CacheStats stats = cache.stats();
System.out.println("命中率: " + stats.hitRate());     // 如 0.92
System.out.println("加载次数: " + stats.loadCount()); // 数据源调用次数

📊 生产建议:将命中率接入 Prometheus + Grafana,实时监控缓存健康度。


七、Caffeine vs Guava Cache

对比项 Guava Cache Caffeine
性能 一般 更高(TinyLFU 算法)
内存占用 较高 更低
功能 基础 更丰富(异步、权重等)
维护状态 停滞 活跃更新
Spring 支持 需手动集成 Spring Boot 3.x 官方支持

✅ 结论 :新项目请直接使用 Caffeine!


八、在 Spring Boot 中使用 Caffeine

8.1 配置 Bean

java 复制代码
@Configuration
public class CacheConfig {

    @Bean
    public Cache<String, User> userCache() {
        return Caffeine.newBuilder()
            .maximumSize(5000)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build();
    }
}

8.2 在 Service 中注入使用

java 复制代码
@Service
public class UserService {

    @Autowired
    private Cache<String, User> userCache;

    public User getUser(String id) {
        return userCache.get(id, this::loadUserFromDB);
    }

    private User loadUserFromDB(String id) {
        // 模拟 DB 查询
        return new User(id, "Name-" + id);
    }
}

💡 提示 :Spring 6+ 已内置 CaffeineCacheManager,可直接用 @Cacheable 注解。


九、常见误区与避坑指南

❌ 误区 1:缓存所有数据

  • 问题:内存爆炸(OOM)
  • 正确做法 :只缓存热点、小、读多写少的数据

❌ 误区 2:不设过期时间

  • 问题:脏数据长期滞留
  • 正确做法 :必须设置 expireAfterWrite 或 expireAfterAccess

❌ 误区 3:用于分布式场景

  • 问题:每个 JVM 实例缓存独立,数据不一致
  • 正确做法 :本地缓存 + Redis 组成多级缓存

十、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
海绵宝宝转agent13 分钟前
操作系统八股开源笔记分享
java·面试
殷色玫瑰31 分钟前
C++ string类详解:常用接口、字符串操作与模拟实现
java·linux·c语言·开发语言·数据结构·c++
CHEEVEN_QY38 分钟前
新能源汽车电池托盘FSW量产的工艺稳定性控制
java·前端·汽车
惊讶的猫1 小时前
MCP-server
java
ZealSinger1 小时前
Boot4升级PostConstruct不跑了
java·spring boot·spring·升级迁移
Code_Solitude1 小时前
C语言:关于二维数组的作业总结
java·c语言·前端
Wang's Blog1 小时前
Java 项目实战: 外卖平台优化-Nginx六种负载均衡策略对比与选型
java·nginx·负载均衡
Wang's Blog1 小时前
Java 项目实战: 外卖平台优化-YApi接口管理平台与文档导入导出
java·开发语言·yapi
专业程序开发源1 小时前
django新闻推荐系统70655-计算机课程设计、毕业设计
java·javascript·spring boot·后端·python·django·课程设计
vx_Biye_Design2 小时前
springboot一站式旅游管理平台81037-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·课程设计·express·旅游