函式庫 / SDK
ben-manes/caffeine avatar
ben-manes/caffeine

Caffeine:围绕淘汰、刷新與引用语义做缓存决策

Java 的高效能快取庫。 Cache Caffeine 使用受 Google Guava 啟發的 API 提供記憶體快取。

17,866 個 Star1,714 個 ForkJavaApache-2.0
GitHub

秒懂

它是什麼?
Caffeine 是 Java 內存缓存庫,沿用 Guava 风格 API,並把容量、時間、引用、监听、統计和异步加载做成可组合选項。
適合誰用?
适合需要進程內缓存、能明确數據新鲜度與容量边界的 Java 服務;不适合把它直接当作跨节点一致的分布式缓存。先用 Java 11 以上和 Caffeine 3.x 在测試服務中驗證命中率、過期、刷新、淘汰监听與並發加载,再决定是否接入 Spring、Quarkus 或其他集成層。
可以商用嗎?
可以。Apache-2.0 是寬鬆授權:你可以使用、修改並販售以它為基礎的軟體,只需保留著作權與授權聲明。
還在維護嗎?
有在維護。儲存庫在最近一天內有新的提交。
用什麼語言寫的?
主要是 Java(依據 GitHub 的語言統計)。

以上回答依據專案的 GitHub 資料(最近同步於 2026年9月15日)與我們的分析,不構成法律意見。

開源專案深度解析

它解决的是進程內缓存问題

README 將 Caffeine 定义為高性能、接近最優的缓存庫,提供受 Guava 啟發的內存缓存 API。典型示例使用 `Caffeine.newBuilder()` 创建 LoadingCache,並组合最大容量、寫入後過期和寫入後刷新。這個模型的边界也很清楚:數據驻留在進程內,跨實例一致性、持久化和远程失效不在 README 的核心承诺裡。

容量和淘汰不是同一件事

可选功能包括超過最大值後的按大小淘汰,淘汰依據結合頻率和新近度;也可按最近访问或最近寫入進行時間過期。設定前要先寫出缓存键的數量上限、单項大小估算和可接受的旧數據時間。只設置一個看起來合理的 `maximumSize`,無法说明內存峰值或業務命中率。

刷新處理第一笔過期请求

README 描述的 `refreshAfterWrite` 会在第一個请求遇到過期狀態時异步刷新。它與 `expireAfterWrite` 的含义不同,刷新和删除不能混為一谈。對外部资源變化敏感的服務,應驗證刷新期間讀到的是旧值還是新值、加载失败如何處理、並發请求是否合並,以及刷新任務是否会把執行器压满。

引用策略需要看對象生命周期

Caffeine 支援對 key 或 value 使用 weak references,也支援 soft references。它们改變的是垃圾回收參與缓存保留的方式,不是稳定的容量控制替代品。若業務要求結果在固定時間內可復用,應先用强引用和明确過期规则建立基線,再评估弱引用對命中率、回收行為和調試可见性的影响。

监听與統计讓缓存可观测

倉庫列出移除通知和访问統计能力,也支援向外部资源传播寫入。监听器可以記錄移除原因、键類型和异常,但不應把完整敏感值寫入日志。統计數據應與请求延迟、後端負载和內存指標一起看;单独提高命中率可能掩盖缓存陈旧或內存增長问題。

版本選擇取决於 Java 基線

README 给出的依赖是 `com.github.ben-manes.caffeine:caffeine:3.2.4`,並说明 Java 11 以上使用 3.x,否则使用 2.x。可选擴展包括 guava 和 jcache。引入時應锁定版本,不要讓擴展模块和核心模块漂移;升級要查看 release notes,並重跑序列化、過期、刷新和並發加载测試。

從单元场景開始驗收

适合用 Caffeine 的服務通常能容忍實例級缓存的边界,並且知道哪些數據可缓存。驗收可構造固定加载器,分别触發容量淘汰、访问過期、寫入過期、刷新失败、移除回調和統计讀取,再在並發條件下观察加载次數。README 提供使用者指南、API 文档和 Maven Central 入口,這些應作為具體 API 的版本依據。测試用例應先固定 `Caffeine.newBuilder()` 的 maximumSize 和 Duration,给每個键設定可观察的加载计數,然後用虚拟時間或等待窗口确認過期行為。對 refreshAfterWrite,要檢查第一次陈旧请求是否触發异步加载、加载期間返回值是什么、异常是否保留旧值。對 weakKeys、weakValues 和 softValues,應讓對象失去强引用後观察回收結果,不要以一次测試的 GC 行為推断稳定策略。啟用 removal listener 後,檢查容量淘汰、時間過期和显式删除能否區分原因,日志中只保留键的安全標识。開啟 statistics 後,將命中率與後端延迟、堆內存和请求量一起記錄。接入 Spring Cache 或 JCache 時還要驗證注解语义是否與直接 API 一致。Caffeine 3.2.4 的 Java 11 基線應進入構建檔案,升級到新 release 後重跑並發加载和序列化测試。

把缓存边界寫進接口说明

明确哪些键可以重建,哪些键過期後必須回源,哪些更新需要主動 invalidate。容量测試逐步增加键數並观察堆占用,不只比較命中率。多實例服務故意讓两個實例缓存不同值,确認团队接受進程內缓存边界;若不能接受,就不能把 Caffeine 当成共享缓存。接入 Guava adapter 或 JCache 時,檢查 null 值、异常传播、监听器線程和執行器關閉。升級 Caffeine 3.2.4 後重跑過期、刷新、並發加载和序列化测試,並把 Java 11 基線锁進構建檔案。 缓存驗收要關注失效後的回源风暴。讓大量请求同時访问刚過期的键,記錄加载次數和後端压力,再测試不同键的並發加载。maximumSize 變化後观察淘汰通知和堆占用。多實例服務故意讓两個實例缓存不同值,确認团队接受進程內缓存边界。接入 Guava adapter 或 JCache 時檢查 null 值、异常传播、监听器線程和執行器關閉。驗收記錄還要包含输入、输出、错误和恢復四類結果。先用最小樣本确認主路径,再增加並發、長文本、權限變化或網络中断,避免只驗證成功截图。每次测試固定版本並保存日志摘要,失败時寫清復現條件和回退動作。素材没有说明的功能保持未知,不用項目热度替代證據。Caffeine 的驗證還應檢查回源次數與堆占用。 失败時保留日志並回到已驗證版本。驗收時先記錄当前版本、執行環境和输入樣本,再記錄成功输出、错误信息、日志位置和回退版本。成功路径至少重復两次,确認結果不是偶然缓存。失败路径要主動制造一次網络中断、權限拒绝、资源不足或參數错误,观察工具是否给出可定位的提示。恢復後重新執行同一输入,比較输出是否完整,确認失败過程没有留下损坏檔案、错误狀態或泄露凭據。测試記錄只保留必要摘要,不上传账號信息、密钥、Cookie、真實使用者數據和受限內容。項目 README 没有明确寫出的能力继续標為未知,不能用相邻項目的经驗补成結論。上線前將這些結果交给實際维护者復核,按版本發布说明逐項确認,發現差异就锁定当前版本並保留回退路径。

針對 caffeine,先依 README 的實際入口執行最小流程,再查看專案指定的輸出、日誌與設定檔。caffeine 的判斷不能只看指令返回成功:要把輸入、版本、權限和產物一起對照,並以檔案未說明的部分標記為未確認。

編輯結論

适合需要進程內缓存、能明确數據新鲜度與容量边界的 Java 服務;不适合把它直接当作跨节点一致的分布式缓存。先用 Java 11 以上和 Caffeine 3.x 在测試服務中驗證命中率、過期、刷新、淘汰监听與並發加载,再决定是否接入 Spring、Quarkus 或其他集成層。 對 caffeine 而言,適合先在隔離環境核對 README 列出的指令與檔案,再決定使用範圍;不適合把檔案未說明的相容性、效能或安全保證當成既定事實。

官方來源

  1. Official README
  2. Project repository
  3. Release notes
社群筆記

社群筆記