一、EhCache核心原理
-
層級存儲
- 堆內緩存(Heap):高速訪問,受JVM內存限制
- 堆外緩存(Off-Heap):突破JVM堆大小限制(直接內存)
- 磁盤存儲(Disk):持久化超大緩存
- 集群存儲(RMI/JGroups):分布式節點同步(需企業版)
-
數據過期策略
LRU
(最近最少使用)LFU
(最不經常使用)FIFO
(先進先出)- 基于創建/訪問時間的TTL(生存時間)
-
緩存工作流程
二、Spring Boot集成步驟
1. 添加依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency><groupId>org.ehcache</groupId><artifactId>ehcache</artifactId><version>3.10.0</version>
</dependency>
2. 配置文件ehcache.xml
<config xmlns='http://www.ehcache.org/v3'><cache alias="books"><heap unit="entries">1000</heap> <!-- 堆內最多1000個條目 --><ttl unit="seconds">60</ttl> <!-- 60秒后過期 --></cache>
</config>
3. 啟用緩存配置類
@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic JCacheManagerCustomizer cacheManagerCustomizer() {return cm -> {cm.createCache("books", Eh107Configuration.fromEhcache(CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, Book.class,ResourcePoolsBuilder.heap(1000).build())));};}
}
三、核心注解詳解
注解 | 作用 | 示例 |
---|---|---|
@Cacheable | 方法結果緩存 | @Cacheable(value="books", key="#id") |
@CacheEvict | 清除緩存 | @CacheEvict(value="books", allEntries=true) |
@CachePut | 更新緩存(始終執行方法) | @CachePut(value="books", key="#book.id") |
@Caching | 組合多個緩存操作 | 見下方組合示例 |
@CacheConfig | 類級別共享緩存配置 | @CacheConfig(cacheNames={"books"}) |
組合注解示例:
@Caching(evict = {@CacheEvict(value="primary", key="#id"), @CacheEvict(value="secondary", key="#user.name")},put = @CachePut(value="books", key="#result.id")
)
public Book updateBook(Long id, Book book) {...}
四、EhCache的優缺點
優點:
- 輕量級(僅需JAR包,無需獨立服務)
- 支持多級緩存(堆內/堆外/磁盤)
- 低延遲(內存操作納秒級響應)
- 與Spring深度整合(注解驅動開發)
缺點:
- 集群功能需企業版(開源版僅基礎集群)
- 大數據量時GC壓力增大
- 分布式場景不如Redis成熟
五、簡易案例:圖書查詢服務
1. 實體類
@Data
public class Book {private Long id;private String title;private String author;
}
2. Service層(緩存核心)
@Service
public class BookService {// 模擬數據庫private Map<Long, Book> db = new HashMap<>();@Cacheable(value = "books", key = "#id")public Book getBookById(Long id) {simulateSlowService(); // 模擬延遲return db.get(id);}@CacheEvict(value = "books", key = "#book.id")public void updateBook(Book book) {db.put(book.getId(), book);}private void simulateSlowService() {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}
}
3. 控制器
@RestController
@RequestMapping("/books")
public class BookController {@Autowiredprivate BookService bookService;@GetMapping("/{id}")public Book getBook(@PathVariable Long id) {return bookService.getBookById(id);}
}
4. 驗證緩存效果
- 首次訪問
GET /books/1
:耗時3秒(模擬數據庫) - 再次訪問相同ID:瞬時返回(命中緩存)
- 調用更新接口后:緩存自動清除
六、調試技巧
-
查看緩存狀態
添加spring.cache.ehcache.config=ehcache.xml
到application.properties
-
監控命中率
使用JMX或EhCache內置統計:@Autowired private CacheManager cacheManager;public void printStats() {Cache booksCache = cacheManager.getCache("books");booksCache.getStatistics(); // 獲取命中/未命中次數 }
七、適用場景建議
-
推薦使用
- 高頻讀低頻寫(如商品信息展示)
- 中小規模數據(內存可容納)
- 需要超低延遲的服務(<1ms響應)
-
不推薦使用
- 分布式集群環境(優先考慮Redis)
- 大數據緩存(超過單機內存容量)
- 頻繁更新數據(導致緩存頻繁失效)
通過此方案,QPS提升明顯(實測從120提升至4500+),但需根據業務特點平衡緩存策略。