Caffeine 本地缓存怎么设计?一次讲清适用场景、淘汰策略、热点保护与一致性边界

大家好,我是一名有 4 年工作经验的 Java 后端开发。
说到缓存,很多人第一反应都是 Redis,但真实项目里,本地缓存往往是非常有效的第一层优化手段。
这篇文章我想系统聊一聊,Caffeine 本地缓存到底什么时候适合用、怎么用、有哪些边界。

🦅个人主页
🐼


一、为什么本地缓存值得用

因为很多场景里,Redis 虽然快,但毕竟还有:

  • 网络开销
  • 序列化开销
  • 热点节点压力

而本地缓存的优势非常直接:

  • JVM 内存命中
  • 延迟更低
  • 能明显分担 Redis 压力

特别适合:

  • 热点读
  • 配置类数据
  • 读多写少数据

二、什么时候适合用 Caffeine

我更推荐用在这些场景:

  • 商品详情热点信息
  • 配置项
  • 字典表
  • 读多写少且允许短时间不一致的数据

不太适合:

  • 强一致写多读少数据
  • 超大对象缓存
  • 需要全局强一致的数据

三、Caffeine 最关键的几个点

3.1 容量上限

本地缓存最怕无限长。

3.2 过期时间

不同数据要有不同 TTL。

3.3 自动加载

适合 Cache Aside 风格。

3.4 统计能力

命中率、淘汰数、加载耗时都值得看。


四、代码示例

private final Cache<Long, ProductDTO> productCache = Caffeine.newBuilder()
        .maximumSize(10_000)
        .expireAfterWrite(Duration.ofSeconds(10))
        .recordStats()
        .build();

public ProductDTO getProduct(Long productId) {
    return productCache.get(productId, this::loadProduct);
}

这个写法的好处是:

  • 有上限
  • 有过期
  • 有统计

五、最容易踩的坑

5.1 没有上限

这和自己用 ConcurrentHashMap 当缓存没区别,很容易把 JVM 内存吃满。

5.2 数据更新后不主动刷新

如果数据有写操作,最好考虑:

  • 主动失效
  • 主动刷新

5.3 把它当强一致缓存

本地缓存天然更适合:

  • 最终一致
  • 短时间可容忍不一致

六、面试中怎么回答

如果面试官问你:

本地缓存一般怎么设计?Caffeine 适合什么场景?

你可以这样回答:

第一,本地缓存特别适合热点读、读多写少、允许短时间不一致的数据,因为它命中在 JVM 内存里,能显著降低 Redis 和数据库压力。

第二,Caffeine 的优势在于它比自己手写 Map 更完善,至少能提供容量控制、过期策略、统计信息和较好的性能实现。

第三,真正落地时我会非常注意边界,比如一定要设置容量上限、合理 TTL、必要时主动刷新,并明确它只适合最终一致场景,不会把它当成强一致缓存。


七、总结

本地缓存真正好用的地方,不是“更快”这么简单,而是:

  • 帮你挡住热点
  • 降低 Redis 压力
  • 缩短响应路径

如果只记一句结论,我觉得可以记住这句:

Caffeine 最适合做读多写少场景下的第一层热点缓存,但一定要记住上限、过期和一致性边界。


八、结尾

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、关注。
后面我会继续整理一些更偏实战的 Java 后端和工程治理文章,尽量少写空泛概念,多写真实项目里会踩到的坑。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐