Caffeine 緩存庫的常用功能使用介紹

🧑 博主簡介:CSDN博客專家歷代文學網(PC端可以訪問:https://literature.sinhy.com/#/?__c=1000,移動端可微信小程序搜索“歷代文學”)總架構師,15年工作經驗,精通Java編程高并發設計Springboot和微服務,熟悉LinuxESXI虛擬化以及云原生Docker和K8s,熱衷于探索科技的邊界,并將理論知識轉化為實際應用。保持對新技術的好奇心,樂于分享所學,希望通過我的實踐經歷和見解,啟發他人的創新思維。在這里,我希望能與志同道合的朋友交流探討,共同進步,一起在技術的世界里不斷學習成長。
技術合作請加本人wx(注明來自csdn):foreast_sea

在這里插入圖片描述


在這里插入圖片描述

Caffeine 緩存庫的常用功能使用介紹

文章目錄

  • Caffeine 緩存庫的常用功能使用介紹
      • 一、基礎緩存操作
      • 二、自動加載緩存(推薦)
      • 三、過期策略配置
        • 1. 全局過期策略
        • 2. 單Key過期(高級用法)
      • 四、淘汰策略配置
      • 五、刷新策略(優于純過期)
      • 六、監聽器與統計
      • 七、異步操作
      • 八、最佳實踐配置模板
      • 九、基于Caffeine實現的動態緩存
      • 關鍵特性說明:
      • 關鍵特性對比表
      • 注意事項:

Caffeine作為新一代高性能Java緩存庫,在并發場景下展現出卓越表現。它通過創新的W-TinyLFU淘汰算法實現高達99%的命中率,并采用無鎖設計使吞吐量較傳統方案提升5-10倍。該庫提供靈活的緩存管理能力:支持基于時間(寫入/訪問過期)、數量或權重的淘汰策略;允許為單個Key設置專屬過期時間;獨創的異步刷新機制能在不阻塞請求的情況下更新數據。開發者可通過簡潔的鏈式API配置內存控制、加載邏輯和事件監聽,輕松構建高并發低延遲的智能緩存系統。其與Guava Cache兼容的接口設計,更使遷移成本降至最低。

以下是 Caffeine 緩存庫的常用功能使用介紹,涵蓋基礎操作、過期策略、淘汰配置等核心功能:


一、基礎緩存操作

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;// 1. 創建緩存實例
Cache<String, Object> cache = Caffeine.newBuilder().build();// 2. 添加數據
cache.put("key1", "value1");// 3. 獲取數據(手動)
Object value = cache.getIfPresent("key1"); // 存在返回value,否則null// 4. 刪除數據
cache.invalidate("key1");
cache.invalidateAll(); // 清空緩存

二、自動加載緩存(推薦)

LoadingCache<String, Object> cache = Caffeine.newBuilder().build(key -> {// 緩存未命中時自動執行的加載邏輯return fetchFromDB(key); // 自定義數據庫加載方法});// 自動加載數據(緩存未命中時執行build中的邏輯)
Object value = cache.get("user_123");

三、過期策略配置

1. 全局過期策略
Cache<String, Object> cache = Caffeine.newBuilder()// 寫入后30分鐘過期.expireAfterWrite(30, TimeUnit.MINUTES)// 最后訪問后15分鐘過期.expireAfterAccess(15, TimeUnit.MINUTES)// 自定義過期策略(按需實現).expireAfter(new Expiry<String, Object>() {public long expireAfterCreate(String key, Object value, long currentTime) {return TimeUnit.MINUTES.toNanos(10); // 創建后10分鐘過期}public long expireAfterUpdate(String key, Object value, long currentTime, long currentDuration) {return currentDuration; // 更新后不改變過期時間}public long expireAfterRead(String key, Object value, long currentTime, long currentDuration) {return currentDuration; // 讀取后不改變過期時間}}).build();
2. 單Key過期(高級用法)
// 創建支持變長過期的緩存
Cache<String, Object> cache = Caffeine.newBuilder().expireAfter(new Expiry<String, Object>() {// ...實現同上}).build();// 為特定Key設置不同過期時間
cache.policy().expireVariably().ifPresent(policy -> {policy.put("hot_key", "value", 2, TimeUnit.HOURS);  // 2小時policy.put("cold_key", "value", 10, TimeUnit.MINUTES); // 10分鐘
});

四、淘汰策略配置

Cache<String, Object> cache = Caffeine.newBuilder()// 基于數量淘汰(最多1000個條目).maximumSize(1000)// 基于權重淘汰(需實現Weigher).maximumWeight(10_000).weigher((String key, Object value) -> {// 自定義權重計算邏輯if (value instanceof String) return ((String) value).length();if (value instanceof List) return ((List<?>) value).size();return 1;})// 基于引用回收(謹慎使用).weakKeys()      // 弱引用Key.weakValues()    // 弱引用Value.softValues()    // 軟引用Value.build();

五、刷新策略(優于純過期)

LoadingCache<String, Object> cache = Caffeine.newBuilder()// 寫入后1分鐘可刷新(不阻塞讀取,異步刷新舊值).refreshAfterWrite(1, TimeUnit.MINUTES).build(key -> fetchFromDB(key));

六、監聽器與統計

Cache<String, Object> cache = Caffeine.newBuilder()// 移除監聽器.removalListener((String key, Object value, RemovalCause cause) -> {System.out.printf("Key %s was removed (%s)%n", key, cause);})// 啟用統計.recordStats().build();// 獲取統計信息
CacheStats stats = cache.stats();
System.out.printf("Hit Rate: %.2f%%, Loads: %d%n",stats.hitRate() * 100, stats.loadCount());

七、異步操作

// 1. 異步緩存
AsyncLoadingCache<String, Object> asyncCache = Caffeine.newBuilder().buildAsync(key -> fetchFromDB(key));// 獲取數據(返回CompletableFuture)
CompletableFuture<Object> future = asyncCache.get("key1");// 2. 同步視圖操作
Object value = asyncCache.synchronous().get("key1");

八、最佳實踐配置模板

LoadingCache<String, Object> optimalCache = Caffeine.newBuilder()// 容量控制.maximumSize(10_000)// 過期策略.expireAfterWrite(30, TimeUnit.MINUTES)// 刷新策略.refreshAfterWrite(5, TimeUnit.MINUTES)// 統計和監聽.recordStats().removalListener((key, value, cause) -> logRemoval(key, cause))// 自動加載.build(key -> fetchFromDB(key));

九、基于Caffeine實現的動態緩存

我們有時候需要這樣一種場景:當用戶請求某個key的時候,該緩存自動從數據庫去加載,就是注冊一個數據庫加載器(自己實現),當獲取不到該key時,自動走數據庫查詢,然后存入該key中。當往caffeine緩存中插入一個key后,如果緩存沒有,則自動存入,并自動同步到數據庫中,當刪除一個key,或key過期后,自動從數據庫同步刪除。

以下是簡單的實現流程:

import com.github.benmanes.caffeine.cache.*;
import java.util.concurrent.TimeUnit;public class DynamicCache<K, V> {private final Cache<K, V> cache;private final DataLoader<K, V> dataLoader;private final DataSynchronizer<K, V> dataSynchronizer;public DynamicCache(DataLoader<K, V> dataLoader, DataSynchronizer<K, V> dataSynchronizer) {this.dataLoader = dataLoader;this.dataSynchronizer = dataSynchronizer;this.cache = Caffeine.newBuilder()// 配置緩存策略(按需設置).expireAfterWrite(30, TimeUnit.MINUTES)  // 30分鐘過期.maximumSize(1000)                      // 最大緩存項// 注冊移除監聽器(用于刪除數據庫數據).removalListener((K key, V value, RemovalCause cause) -> {if (cause.wasEvicted()) {  // 僅處理過期或容量剔除dataSynchronizer.deleteFromDatabase(key);}})// 注冊加載器(用于緩存未命中時從DB加載).build(key -> {V value = dataLoader.loadFromDatabase(key);if (value == null) throw new Exception("Key not found");return value;});}// 獲取數據(自動加載)public V get(K key) {return cache.get(key, k -> {V value = dataLoader.loadFromDatabase(k);if (value == null) throw new RuntimeException("Data not found");return value;});}// 添加/更新數據(同步到數據庫)public void put(K key, V value) {// 先同步到數據庫dataSynchronizer.saveToDatabase(key, value);// 再更新緩存cache.put(key, value);}// 刪除數據(同步刪除數據庫)public void delete(K key) {// 先刪除數據庫數據dataSynchronizer.deleteFromDatabase(key);// 再使緩存失效cache.invalidate(key);}// 數據庫加載器接口public interface DataLoader<K, V> {V loadFromDatabase(K key);}// 數據庫同步器接口public interface DataSynchronizer<K, V> {void saveToDatabase(K key, V value);void deleteFromDatabase(K key);}
}

上述接口使用示例:

// 1. 實現數據庫操作接口
DynamicCache.DataLoader<String, User> loader = key -> jdbcTemplate.queryForObject("SELECT * FROM users WHERE id=?", User.class, key);DynamicCache.DataSynchronizer<String, User> synchronizer = new DynamicCache.DataSynchronizer<>() {@Overridepublic void saveToDatabase(String key, User value) {jdbcTemplate.update("INSERT OR REPLACE INTO users (id, name) VALUES (?, ?)", key, value.getName());}@Overridepublic void deleteFromDatabase(String key) {jdbcTemplate.update("DELETE FROM users WHERE id=?", key);}
};// 2. 創建緩存實例
DynamicCache<String, User> userCache = new DynamicCache<>(loader, synchronizer);// 3. 使用緩存
// 自動加載(緩存未命中時從DB加載)
User user = userCache.get("user123");  // 添加/更新(同步到DB)
userCache.put("user456", new User("Alice"));// 刪除(同步刪除DB數據)
userCache.delete("user789");

關鍵特性說明:

  1. 自動加載

    • 當調用 get() 方法且緩存未命中時,自動通過 DataLoader 從數據庫加載
    • 加載成功后自動填充緩存
  2. 寫穿透

    • put() 操作時:
      • 先通過 DataSynchronizer 保存到數據庫
      • 再更新緩存
    • 保證數據庫與緩存的數據一致性
  3. 刪除同步

    • delete() 操作時:
      • 先刪除數據庫數據
      • 再使緩存失效
    • 緩存過期/淘汰時:
      • 通過 RemovalListener 自動觸發數據庫刪除
  4. 緩存配置

    • 可自定義過期時間(expireAfterWrite
    • 可設置最大容量(maximumSize
    • 支持其他Caffeine特性(刷新策略、弱引用等)

關鍵特性對比表

功能配置方法適用場景
寫入過期expireAfterWrite()數據更新頻率低的場景
訪問過期expireAfterAccess()讀多寫少的場景
自適應過期expireAfter(Expiry)需要動態過期時間的場景
數量淘汰maximumSize()通用場景
權重淘汰maximumWeight() + weigher()緩存對象大小差異大的場景
異步刷新refreshAfterWrite()高并發讀取+后臺更新
弱/軟引用weakKeys()/softValues()內存敏感型應用

注意事項:

  1. 刷新 vs 過期

    • 刷新 (refreshAfterWrite) 異步更新舊值,不阻塞請求
    • 過期 (expireAfterWrite) 會阻塞請求直到新值加載完成
  2. 權重計算

    • 確保 weigher 計算快速(納秒級)
    • 權重總和不超過 maximumWeight
  3. 過期時間精度

    • 默認時間精度≈1秒,需要毫秒級精度可配置:
    .scheduler(Scheduler.systemScheduler())
    
  4. 并發加載控制

    • 相同key并發請求時,只有一個線程執行加載
    • 可通過 executor() 指定自定義線程池

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/91202.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/91202.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/91202.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C# _列表(List<T>)_ 字典(Dictionary<TKey, TValue>)

目錄 列表&#xff08;List&#xff09;特點 創建列表 RemoveAll 刪除與之條件相匹配的數據 會返回刪除的個數 Capacity 獲取或設置列表的容量 更多方法可參照上篇文章&#xff1a;C#_ArrayList動態數組 字典&#xff08;Dictionary&#xff09;特點 定義一個字典 向字…

【實時Linux實戰系列】實時網絡控制與調度

在實時控制系統中&#xff0c;網絡調度是確保實時數據流傳輸和處理不受延遲影響的關鍵。實時網絡控制與調度技術對于工業自動化、金融交易、多媒體流等領域至關重要。通過合理設計網絡調度策略&#xff0c;可以顯著提高系統的實時性和可靠性。本文將介紹如何在實時控制系統中實…

Qwen3-Coder:介紹及使用 -- 超強AI編程助手

更多內容&#xff1a;XiaoJ的知識星球 目錄一、Qwen3-Coder模型介紹1.預訓練階段&#xff08;Pre-Training&#xff09;2.后訓練階段&#xff08;Post-Training&#xff09;1&#xff09;Scaling Code RL: Hard to Solve, Easy to Verify2&#xff09;Scaling Long-Horizon RL二…

uniapp 如果進入頁面輸入框自動聚焦,此時快速返回頁面或者跳轉到下一個頁面,輸入法頂上來的頁面出現半屏的黑屏問題。

如果進入頁面輸入框自動聚焦&#xff0c;此時快速返回頁面或者跳轉到下一個頁面&#xff0c;輸入法頂上來的頁面出現半屏的黑屏問題。輸入法出來后&#xff0c;設置了自動將頁面頂上來的配置&#xff1a;pages.json"softinputMode": "adjustResize""g…

深入了解 Kubernetes(k8s):從概念到實踐

目錄 一、k8s 核心概念 二、k8s 的優勢 三、k8s 架構組件 控制平面組件 節點組件 四、k8s docker 運行前后端分離項目的例子 1. 準備前端項目 2. 準備后端項目 3. 創建 k8s 部署配置文件 4. 部署應用到 k8s 集群 在當今云計算和容器化技術飛速發展的時代&#xff0c…

Android User版本默認用test-keys,如何改用release-keys

Android User版本 默認用test-keys&#xff0c; 如何改用release-keys 開發云 - 一站式云服務平臺 --- build/core/Makefile | 5 1 file changed, 5 insertions() diff --git a/build/core/Makefile b/build/core/Makefile index --- a/build/core/Makefile b/build/core…

從零開始學習Dify-數據庫數據可視化(五)

概述上一篇文章我們圍繞 Excel 文件展開數據可視化教學&#xff0c;逐步掌握了數據導入、圖表構建和 AI 智能分析。在實際業務環境中&#xff0c;很多數據并不是保存在表格中&#xff0c;而是存儲于數據庫系統中&#xff0c;尤其是最常見的 MySQL。本篇作為本系列的第五篇&…

使用vue2和 element-ui 做一個點餐收銀臺系統前端靜態項目

今天給大家分享一個 關于點餐收銀臺的靜態網站&#xff0c;最近一直在練習前端項目&#xff0c;就使用vue2和 element-ui 做了一個 這樣簡單的 收銀臺系統。先給大家看一下 做出來的樣子。 因為是練習項目 所以頁面功能還是比較簡單的。 使用的技術是&#xff1a; 技術棧 Vu…

Spring Boot自動配置原理深度解析

Spring Boot自動配置原理深度解析 一、自動配置核心概念 1.1 什么是自動配置 Spring Boot自動配置(Auto-Configuration)是其核心特性之一&#xff0c;能夠根據項目依賴自動配置Spring應用程序。例如&#xff1a; 當檢測到H2數據庫依賴時&#xff0c;自動配置內存數據庫當存在Sp…

關于 Apache Ignite 中 Job 調度(Job Scheduling)與沖突控制(Collision Control) 的機制說明

這段內容是關于 Apache Ignite 中 Job 調度&#xff08;Job Scheduling&#xff09;與沖突控制&#xff08;Collision Control&#xff09; 的機制說明。我來為你逐段解析&#xff0c;幫助你深入理解其原理和使用方式。&#x1f50d; 一、核心概念&#xff1a;Job 調度與 Colli…

網絡資源模板--基于Android Studio 實現的課程管理App

目錄 一、測試環境說明 二、項目簡介 三、項目演示 四、部設計詳情&#xff08;部分) 登錄頁 首頁 五、項目源碼 一、測試環境說明 電腦環境 Windows 11 編寫語言 JAVA 開發軟件 Android Studio (2020) 開發軟件只要大于等于測試版本即可(近幾年官網直接下載也可…

ROUGE-WE:詞向量化革新的文本生成評估框架

一、ROUGE 基礎與核心局限 ROUGE&#xff08;Recall-Oriented Understudy for Gisting Evaluation&#xff09; 是自動文本摘要與機器翻譯的主流評估指標&#xff0c;由 Chin-Yew Lin 在2004年發表的論文中首次系統提出。其核心變體包括&#xff1a; ROUGE-N&#xff1a;基于…

MGER綜合實驗

一.拓撲二、實驗需求 1、R5為ISP&#xff0c;只能進行IP地址配置&#xff0c;其所有地址均配為公有IP地址; 2、R1和R5間使用PPP的PAP認證&#xff0c;R5為主認證方; R2與R5之間使用ppp的CHAP認證&#xff0c;R5為主認證方; R3與R5之間使用HDLC封裝; 3、R1、R2、R3構建一個MGRE環…

高可用集群Keepalived、Redis、NoSQL數據庫Redis基礎管理

1. 總結負載均衡常見的算法 輪詢 (Round Robin)&#xff1a;按順序將請求依次分配給后端服務器&#xff0c;適合服務器性能相近的場景。 加權輪詢 (Weighted Round Robin)&#xff1a;在輪詢的基礎上&#xff0c;根據服務器的權重分配請求。 隨機 (Random)&#xff1a;隨機選…

【深度學習】獨熱編碼(One-Hot Encoding)

獨熱編碼&#xff08;One-Hot Encoding&#xff09; 在機器學習中&#xff0c;數據預處理是不可或缺的關鍵一步。面對各種非數值類型的分類數據&#xff08;Categorical Data&#xff09;&#xff0c;如何將其轉換為機器學習模型能夠“理解”的語言呢&#xff1f;獨熱編碼&…

Promise完全體總結

我們在上篇文章提到了異步會導致無法通過返回值來獲取函數的執行結果&#xff0c;我們通過傳入一個回調函數的方式&#xff0c;以參數的形式獲取到了我們想要獲取的數據&#xff0c;但是這樣如果需要對數據進行多次操作導致形成回調地獄那種不便于閱讀以及護理的代碼。為了解決…

SpringJDBC源碼初探-DataSource類

一、DataSource接口核心作用 DataSource是JDBC規范的核心接口&#xff0c;位于javax.sql包中&#xff0c;用于替代傳統的DriverManager獲取數據庫連接。Spring框架通過org.springframework.jdbc.datasource包對該接口進行了增強&#xff0c;提供連接池管理、事務綁定等高級特性…

C語言(08)——關于指針(逐漸清晰版)

為了更好地理解本篇文章的知識內容&#xff0c;讀者可以將以下文章作為補充知識進行閱讀 &#xff1a; C語言————原碼 補碼 反碼 &#xff08;超絕詳細解釋&#xff09;-CSDN博客 C語言————二、八、十、十六進制的相互轉換-CSDN博客 C語言————斐波那契數列的理解…

LeetCode 1616.分割兩個字符串得到回文串

給你兩個字符串 a 和 b &#xff0c;它們長度相同。請你選擇一個下標&#xff0c;將兩個字符串都在 相同的下標 分割開。由 a 可以得到兩個字符串&#xff1a; aprefix 和 asuffix &#xff0c;滿足 a aprefix asuffix &#xff0c;同理&#xff0c;由 b 可以得到兩個字符串 …

算法【1】

網址&#xff1a;主站 工具補充 1. sort 函數的使用規則 作用&#xff1a;對容器元素進行排序&#xff0c;默認升序。語法&#xff1a;sort(起始迭代器, 結束迭代器, 比較規則) 前兩個參數是排序范圍&#xff1a;[begin, end)&#xff08;包含begin&#xff0c;不包含end&am…