快取模組
AppFuse Server 提供基於分層架構 + 適配器模式的快取工具集。
核心特色
1. 介面導向設計
底層可從 Ehcache 切換到 Caffeine/Redis,應用程式碼無需修改。
2. 管理功能
- 停用/啟用: 系統維護時暫時停用快取
- 層級清除: 精確控制清除範圍
- 狀態查詢: 即時監控命中率、容量使用
3. 雙層快取架構 (DualLayerCache)
- 快速層: 短期熱資料,可過期
- 持久層: 長期全量資料,永不過期
- 自動降級: 快速層 miss 時自動查詢持久層
標準快取
基本用法
import io.leandev.appfuse.cache.*;
// 建立快取
Cache<String, User> userCache = CacheBuilder
.newCache(cacheManager, "users", String.class, User.class)
.heap(100) // 堆內 100 條
.offheap(20) // 堆外 20MB
.ttl(30) // 30 分鐘過期
.build();
// 使用快取
userCache.put("user1", user);
User user = userCache.get("user1");
userCache.remove("user1");
Cache-Aside Pattern
public Optional<User> findById(String id) {
// 1. 先查快取
User cached = userCache.get(id);
if (cached != null) {
return Optional.of(cached);
}
// 2. 快取未命中,查資料庫
return userRepository.findById(id)
.map(user -> {
// 3. 寫入快取
userCache.put(id, user);
return user;
});
}
雙層快取
適用於需要容錯的場景,如 Session 管理。
import io.leandev.appfuse.cache.*;
// 建立雙層快取
DualLayerCache<String, Session> sessionCache = DualCacheBuilder
.newCache(cacheManager, "sessions", String.class, Session.class)
.fastHeap(100) // 快速層:堆內 100 條
.fastOffheap(10) // 快速層:堆外 10MB
.fastTtl(30) // 快速層:30 分鐘過期
.store(200) // 持久層:200 條
.build();
// 自動降級:快速層 miss 時自動查詢持久層
String userId = sessionCache.get(sessionId);
// 不降級模式
String userId = sessionCache.get(sessionId, false);
雙層快取架構圖
快取啟用開關
CacheManager 提供管理器層級的啟用/停用開關(ADR-007),主要供除錯/測試「強制讀資料源」。停用語意為邏輯旁路、不清空資料——停用期間 get 強制 miss、put 被忽略,底層資料保留,重新啟用即可再服務。
管理器層總閘
disableAll() 一次停用此管理器下所有 managed 快取;enableAll() 翻回總閘。停用後新建立(含懶建)的 managed 快取也自動受總閘管制;enableAll() 僅翻回總閘,不會覆蓋個別快取以 disableCache() 設定的停用狀態。
cacheManager.disableAll(); // 全部停用:每次 get 都 miss、強制讀資料源
cacheManager.enableAll(); // 恢復服務
boolean on = cacheManager.isEnabled(); // 查詢總閘狀態
個別快取開關
disableCache(name) / enableCache(name) 停用/啟用單一快取,與總閘正交——即使總閘啟用,被指名的快取仍停用。可在快取建立之前先指名,之後懶建的同名快取會以停用狀態誕生。有效服務狀態為兩層 AND:總閘 isEnabled() AND 個別開關。
cacheManager.disableCache("users"); // 只停用 users 快取
boolean served = cacheManager.isCacheEnabled("users"); // 總閘 AND 個別開關
停用 ≠ 清空:停用是旁路、不動底層資料;如需新鮮資料另以
clear()處理。
Property 接線由消費端承擔
框架只提供 disableAll() / disableCache() 等介面原語,不出貨 @AutoConfiguration / @ConfigurationProperties。將設定(如 app.cache.enabled / app.cache.disabled-caches)接到原語呼叫,是消費端的責任——參考實作的 CacheConfig 示範了這段接線:
// 參考實作 CacheConfig(消費端):讀設定→呼叫原語
if (!cacheEnabled) { // app.cache.enabled=false
cacheManager.disableAll();
} else {
disabledCaches.forEach(cacheManager::disableCache); // app.cache.disabled-caches=users,rateLimit
}
此接線在 CacheManager 建立時即套用,故即使各快取 bean 稍後才建立(DI 順序在後或懶建)仍正確受管。詳見 ADR-007: 快取啟用開關。
快取模式比較
| 模式 | 適用場景 | 範例 |
|---|---|---|
| Cache-Aside | 使用者資訊、產品資料 | UserCacheService |
| Write-Through | 需要強一致性的場景 | 訂單狀態 |
| Time-to-Idle | API 限流、防爆破 | RateLimitService |
詳細 API
請參閱 Cache API 參考 或 Javadoc。