初识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 使用软引用(内存不足时回收)

⚠️ 注意maximumSizeweak/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:不设过期时间

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

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

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

十、结语

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

相关推荐
咸鱼2.01 小时前
【java入门到放弃】Dubbo
java·开发语言·dubbo
JAVA面经实录9177 小时前
Java企业级工程化·终极完整版背诵手册(无遗漏、全覆盖、面试+落地通用)
java·开发语言·面试
Flying pigs~~8 小时前
RAG智慧问答项目
数据库·人工智能·缓存·微调·知识库·rag
许彰午9 小时前
CacheSQL(二):主从复制——OpLog 环形缓冲区与故障自动恢复
java·数据库·缓存
Bat U10 小时前
JavaEE|多线程初阶(七)
java·开发语言
掌心向暖RPA自动化12 小时前
如何获取网页某个元素在屏幕可见部分的中心坐标影刀RPA懒加载坐标定位技巧
java·javascript·自动化·rpa·影刀rpa
日取其半万世不竭13 小时前
Minecraft Java版社区服务器搭建教程(Linux,适合新手)
java·linux·服务器
TeamDev13 小时前
JxBrowser 9.0.0 版本发布啦!
java·前端·混合应用·jxbrowser·浏览器控件·跨平台渲染·原声输入
AI人工智能+电脑小能手14 小时前
【大白话说Java面试题】【Java基础篇】第24题:Java面向对象有哪些特征
java·开发语言·后端·面试
AI人工智能+电脑小能手14 小时前
【大白话说Java面试题】【Java基础篇】第25题:JDK1.8的新特性有哪些
java·开发语言·后端·面试