一、在Spring Boot(1.x版本)中集成Guava Cache
1. 添加依賴
在pom.xml
中添加Guava依賴:
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.0.1-jre</version> <!-- 使用最新版本 -->
</dependency>
2. 啟用緩存支持
在啟動類上添加@EnableCaching
注解:
@SpringBootApplication
@EnableCaching
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}
3. 配置Guava緩存管理器
創建配置類定義CacheManager
Bean:
@Configuration
public class CacheConfig {@Beanpublic CacheManager cacheManager() {GuavaCacheManager cacheManager = new GuavaCacheManager();cacheManager.setCacheBuilder(CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES) // 寫入10分鐘后過期.maximumSize(100) // 最大緩存數量.recordStats()); // 開啟統計信息return cacheManager;}
}
4. 使用緩存注解
在Service層使用@Cacheable
、@CacheEvict
等注解:
@Service
public class UserService {// 緩存查詢結果,key為id@Cacheable(value = "USER_CACHE", key = "#id")public User getUserById(Long id) {return userRepository.findById(id).orElse(null);}// 更新緩存@CachePut(value = "USER_CACHE", key = "#user.id")public User updateUser(User user) {return userRepository.save(user);}// 刪除緩存@CacheEvict(value = "USER_CACHE", key = "#id")public void deleteUser(Long id) {// 刪除用戶邏輯userRepository.deleteById(id);}}
5. 驗證緩存效果
編寫測試類或調用接口驗證緩存是否生效:
@SpringBootTest
public class UserServiceTest {@Autowiredprivate UserService userService;@Testpublic void testCache() {// 第一次調用,執行方法User user1 = userService.getUserById("123");// 第二次調用,從緩存獲取User user2 = userService.getUserById("123");// 驗證是否為同一對象(緩存生效)assertThat(user1).isSameAs(user2);}
}
高級配置
-
多緩存配置:為不同緩存設置不同策略:
@Bean public CacheManager cacheManager() {GuavaCacheManager cacheManager = new GuavaCacheManager();cacheManager.setCacheBuilder(CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).maximumSize(500));cacheManager.setCacheBuilder("userCache", CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).maximumSize(100));return cacheManager; }
-
刷新策略:使用
refreshAfterWrite
定時刷新(需配合LoadingCache):CacheBuilder.newBuilder().refreshAfterWrite(5, TimeUnit.MINUTES).build(CacheLoader.from(key -> loadData(key)));
-
統計信息:通過
recordStats()
啟用統計,使用cache.getStatistics()
獲取命中率等信息。
常見問題
-
緩存未生效:
- 確保啟動類有
@EnableCaching
。 - 檢查方法是否為
public
(注解在私有方法上無效)。
- 確保啟動類有
-
配置未應用:
- 確認
CacheManager
Bean正確注冊。 - 檢查緩存名稱是否匹配
@Cacheable(value = "cacheName")
。
- 確認
-
內存溢出:
- 合理設置
maximumSize
或expireAfterAccess/Write
。
- 合理設置
通過以上步驟,即可在Spring Boot中高效使用Guava Cache實現本地緩存,提升應用性能。
二、Spring Boot 2.x及以上版本(推薦使用Caffeine)
在Spring Boot 2.x及以上版本中,Caffeine作為默認的本地緩存組件,取代了Guava Cache,提供了更高的性能和更靈活的配置。
1. 添加依賴
需引入spring-boot-starter-cache
和caffeine
依賴:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1.8</version> <!-- 推薦使用最新版本 -->
</dependency>
2. 啟用緩存支持
在啟動類添加@EnableCaching
注解:
@SpringBootApplication
@EnableCaching
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}
3. 配置Caffeine緩存
方式一:通過配置文件
在application.yml
中定義全局緩存參數:
spring:cache:type: caffeinecaffeine:spec: maximumSize=500,expireAfterWrite=600s,initialCapacity=100cache-names: userCache, productCache # 定義緩存名稱
- 常用參數:
maximumSize
:最大緩存條目數expireAfterWrite
:寫入后過期時間initialCapacity
:初始容量。
方式二:通過Java Config類
為不同緩存設置獨立策略(推薦多緩存場景):
@Configuration
@EnableCaching
public class CacheConfig {public enum Caches {USER_CACHE(600, 1000), // 有效期600秒,最大容量1000PRODUCT_CACHE(3600);private final int ttl;private final int maxSize;Caches(int ttl, int maxSize) {this.ttl = ttl;this.maxSize = maxSize;}public int getTtl() {return ttl;}public int getMaxSize() {return maxSize;}}@Beanpublic CacheManager cacheManager() {SimpleCacheManager manager = new SimpleCacheManager();List<CaffeineCache> caches = Arrays.stream(Caches.values()).map(c -> new CaffeineCache(c.name(), Caffeine.newBuilder().expireAfterWrite(c.getTtl(), TimeUnit.SECONDS).maximumSize(c.getMaxSize()).build())).collect(Collectors.toList());manager.setCaches(caches);return manager;}
}
此方式支持為每個緩存單獨配置過期時間和容量。
4. 使用緩存注解
在Service層通過注解操作緩存:
@Service
public class UserService {// 緩存查詢結果,key為id@Cacheable(value = "USER_CACHE", key = "#id")public User getUserById(Long id) {return userRepository.findById(id).orElse(null);}// 更新緩存@CachePut(value = "USER_CACHE", key = "#user.id")public User updateUser(User user) {return userRepository.save(user);}// 刪除緩存@CacheEvict(value = "USER_CACHE", key = "#id")public void deleteUser(Long id) {userRepository.deleteById(id);}
}
- 注解說明:
@Cacheable
:查詢時優先從緩存讀取@CachePut
:更新數據并刷新緩存@CacheEvict
:刪除數據時移除緩存。
5. 高級配置
刷新策略(RefreshAfterWrite)
需定義CacheLoader
以支持自動刷新:
@Bean
public CacheLoader<Object, Object> cacheLoader() {return new CacheLoader<>() {@Overridepublic Object load(Object key) {return loadDataFromDB(key); // 初始加載數據}@Overridepublic Object reload(Object key, Object oldValue) {return oldValue; // 刷新時保留舊值,異步加載新值}};
}
配置文件中需添加refreshAfterWrite=5s
,并關聯此Bean。
統計與監控
啟用統計功能:
Caffeine.newBuilder().recordStats().build();
通過cache.stats()
獲取命中率、回收數量等指標。
6. 驗證緩存效果
通過測試類驗證緩存是否生效:
@SpringBootTest
public class CacheTest {@Autowiredprivate UserService userService;@Testpublic void testCache() {User user1 = userService.getUserById(1L); // 首次查詢,存入緩存User user2 = userService.getUserById(1L); // 二次查詢,命中緩存assertThat(user1).isSameAs(user2);}
}
常見問題
-
緩存未命中:
- 檢查方法是否為
public
(注解在私有方法無效) - 確認緩存名稱與配置一致。
- 檢查方法是否為
-
配置沖突:
- 避免同時配置
maximumSize
和maximumWeight
expireAfterWrite
優先級高于expireAfterAccess
。
- 避免同時配置
通過以上步驟,可在Spring Boot 2.x中高效集成Caffeine,實現高性能本地緩存,適用于高頻訪問但更新較少的數據場景(如配置信息、靜態數據)。
三、Caffeine使用場景
Caffeine 作為高性能本地緩存庫,適用于多種需要快速數據訪問和高效內存管理的場景。以下是其主要使用場景及對應的技術優勢分析:
1. 高并發請求緩存
- 場景描述:適用于高頻訪問的接口或熱點數據,例如用戶信息查詢、商品詳情展示等。Caffeine 通過無鎖并發設計和 Window TinyLFU 算法,顯著提升緩存命中率,減少數據庫壓力。
- 技術優勢:
- 高性能:在高并發環境下,Caffeine 的吞吐量遠超 Guava Cache,其分段鎖機制避免了鎖競爭問題。
- 高命中率:Window TinyLFU 算法結合 LRU 和 LFU 優點,有效保留高頻訪問數據,命中率比 Guava 提升 10%~20%。
- 典型應用:Web 應用的 API 接口緩存,如電商平臺的商品詳情頁。
2. 數據庫查詢緩存
- 場景描述:用于緩存頻繁查詢的數據庫結果,如用戶常用配置、熱門商品庫存等,減少重復數據庫訪問。
- 技術優勢:
- 自動過期策略:支持
expireAfterWrite
(寫入后過期)和expireAfterAccess
(訪問后過期),防止數據過時。 - 內存管理:通過
maximumSize
限制緩存條目數,避免內存溢出,結合惰性刪除和定時清理機制優化內存使用。
- 自動過期策略:支持
- 典型應用:用戶登錄信息緩存、商品庫存實時查詢緩存。
3. 復雜計算結果緩存
- 場景描述:緩存計算密集型操作的結果,如圖像處理、大數據聚合分析等,避免重復計算消耗資源。
- 技術優勢:
- 異步加載:通過
AsyncLoadingCache
異步加載數據,減少主線程阻塞,提升系統響應速度。 - 刷新機制:使用
refreshAfterWrite
定時刷新緩存,保證數據更新后的及時性,同時保留舊數據直至新數據加載完成。
- 異步加載:通過
- 典型應用:推薦系統的實時計算結果緩存、圖像處理后的縮略圖緩存。
4. 多級緩存架構(L1緩存)
- 場景描述:在分布式系統中作為一級本地緩存(L1),結合 Redis(L2)和數據庫(L3)形成三級緩存,減少跨服務或跨節點的網絡延遲。
- 技術優勢:
- 低延遲訪問:本地內存訪問速度極快,適合對延遲敏感的場景。
- 靈活集成:通過
CacheLoader
和Writer
接口,可無縫與 Redis 等外部緩存聯動,實現數據回源和同步。
- 典型應用:秒殺系統的庫存緩存、分布式服務中的配置信息緩存。
5. 需要高靈活性和統計監控的場景
- 場景描述:對緩存策略有定制化需求(如動態調整過期時間、監聽緩存事件)或需監控緩存命中率的場景。
- 技術優勢:
- 靈活配置:支持基于大小、時間、引用等多種淘汰策略,并可自定義過期邏輯。
- 統計功能:通過
recordStats()
啟用統計,獲取命中率、淘汰次數等指標,便于性能調優。
- 典型應用:實時監控系統的緩存健康狀態、需要動態調整緩存策略的業務場景。
注意事項
- 非分布式場景:Caffeine 僅適用于本地緩存,跨節點數據需結合 Redis 等分布式緩存。
- 內存限制:需根據應用內存合理設置
maximumSize
或權重,避免 OOM 問題。 - 數據一致性:本地緩存可能導致多實例間數據不一致,需通過過期時間或事件通知機制解決。
總結
Caffeine 憑借其高性能、高命中率和靈活的配置,成為高并發、低延遲場景下的首選本地緩存庫。尤其適合作為一級緩存與 Redis 等組成多級緩存架構,或用于需要快速響應和復雜策略管理的業務場景。實際應用中需結合具體需求調整淘汰策略和內存配置,以最大化其優勢。
更多用法:
SpringBoot:第五篇 集成Guava(本地緩存+分布式緩存)