這份文檔是關于 如何使用 Apache Ignite 作為 Spring 框架的緩存(Spring Cache)后端,實現方法級別的緩存功能。
這和前面我們講的 Spring Data + Ignite 是兩個不同的概念。我們先明確區別,再深入理解。
🔁 一、核心區別:Spring Data vs Spring Cache
對比項 | Spring Data + Ignite | Spring Cache + Ignite |
---|---|---|
目的 | 主動操作緩存數據,像操作數據庫一樣存取 Ignite 中的數據 | 自動緩存方法結果,避免重復執行耗時方法 |
編程模型 | 寫 Repository 接口,調用 save() , findByXxx() | 給方法加注解 @Cacheable , @CacheEvict |
數據來源 | 數據主要來自 Ignite 緩存 | 數據來自方法執行結果(如查數據庫) |
是否生成 SQL | ? 是(根據方法名自動生成) | ? 否(只是緩存結果) |
典型場景 | 你想直接讀寫 Ignite 緩存 | 你想緩存數據庫查詢結果 |
? 簡單說:
- Spring Data:你主動管理緩存里的數據。
- Spring Cache:你讓 Spring 自動幫你緩存某個方法的結果。
🧠 二、Spring Cache + Ignite 的核心思想
💡 目標:避免重復執行耗時的操作(如數據庫查詢、遠程調用),直接從緩存中返回結果。
舉個例子:
@Cacheable("averageSalary")
public long averageSalary(int organizationId) {// 耗時操作:查數據庫return jdbc.queryForObject("SELECT AVG(salary)...", organizationId);
}
第一次調用 averageSalary(101)
:
- 方法執行 → 查數據庫 → 返回結果 → 同時存入 Ignite 緩存(key=101, value=50000)
第二次調用 averageSalary(101)
:
- Spring 檢查緩存中是否有 key=101 的數據
- 有 → 直接返回緩存結果,跳過方法執行
? 效果:提升性能,減輕數據庫壓力
?? 三、如何配置 Ignite 作為 Spring Cache Manager?
Spring Cache 是一個抽象層,它不關心底層用的是 Redis、Ehcache 還是 Ignite。
你要做的就是:提供一個 CacheManager
實現,告訴 Spring 用 Ignite 來存緩存數據。
步驟 1:引入依賴(Maven)
確保你的 pom.xml
包含:
<dependency><groupId>org.apache.ignite</groupId><artifactId>ignite-spring</artifactId><version>${ignite.version}</version>
</dependency>
?
ignite-spring
模塊包含了SpringCacheManager
步驟 2:配置 SpringCacheManager
在 Spring 配置文件(XML 或 Java Config)中定義 SpringCacheManager
。
方式一:由 SpringCacheManager 自動啟動 Ignite 節點
<bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager"><!-- 指定 Ignite 配置文件路徑 --><property name="configurationPath" value="config/ignite-config.xml"/>
</bean><!-- 啟用注解驅動的緩存 -->
<cache:annotation-driven/>
方式二:使用已存在的 Ignite 節點(推薦集群環境)
<bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager"><!-- 使用已啟動的節點(gridName 對應 IgniteConfiguration.setIgniteInstanceName()) --><property name="gridName" value="myIgniteInstance"/>
</bean><cache:annotation-driven/>
?
gridName
:如果你已經在別處(如 ServletListener)啟動了 Ignite 節點,就用這個名字關聯它。
🌟 四、動態緩存(Dynamic Caches)
你不需要提前創建所有緩存!
當 Spring 第一次使用某個緩存名(如 "averageSalary"
)時,如果緩存不存在,SpringCacheManager
會自動創建它。
自定義動態緩存配置
你可以設置默認的緩存模板:
<bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager"><property name="configurationPath" value="ignite.xml"/><!-- 所有動態創建的緩存都使用 REPLICATED 模式 --><property name="dynamicCacheConfiguration"><bean class="org.apache.ignite.configuration.CacheConfiguration"><property name="cacheMode" value="REPLICATED"/></bean></property><!-- 啟用 Near Cache(本地緩存),提升讀取性能 --><property name="dynamicNearCacheConfiguration"><bean class="org.apache.ignite.configuration.NearCacheConfiguration"><property name="nearStartSize" value="1000"/></bean></property>
</bean>
? Near Cache:在應用節點本地再緩存一份數據,減少網絡開銷。
🧩 五、使用緩存注解(核心)
1. @Cacheable
—— 緩存方法結果
@Cacheable("averageSalary") // 緩存名為 "averageSalary"
public long averageSalary(int organizationId) {// 耗時操作:查數據庫return jdbc.queryForObject("SELECT AVG(salary)...", Long.class, organizationId);
}
- key 生成規則:默認使用所有參數做 key(這里就是
organizationId
) - 效果:相同參數只執行一次,后續直接返回緩存
2. @CacheEvict
—— 刪除緩存(數據變更時用)
@CacheEvict(value = "averageSalary", key = "#e.organizationId")
public void updateSalary(Employee e) {jdbc.update("UPDATE Employee SET salary = ? WHERE id = ?", e.getSalary(), e.getId());
}
value = "averageSalary"
:指定要清除的緩存名key = "#e.organizationId"
:使用 Spring EL(表達式語言) 提取e
對象的organizationId
字段作為緩存 key- 作用:員工薪資變了 → 對應部門的平均工資緩存失效 → 下次調用
averageSalary()
會重新計算
? 這是保持緩存一致性的關鍵!
3. 其他常用注解
注解 | 說明 |
---|---|
@CachePut | 強制執行方法,并更新緩存(不管是否存在) |
@Caching | 組合多個緩存操作(如同時 @CacheEvict 多個緩存) |
@CacheConfig | 類級別配置(如統一設置 cacheNames) |
🎯 六、實際工作流程圖解
調用 averageSalary(101)↓
Spring 檢查 Ignite 緩存中是否存在 key=101 的數據├─ 存在 → 直接返回緩存值 ?└─ 不存在 → 執行方法體(查數據庫)↓得到結果(如 50000)↓將 (101, 50000) 存入 Ignite 的 "averageSalary" 緩存↓返回結果
當 updateSalary(employee)
被調用:
執行 updateSalary(e)↓
Spring 清除 "averageSalary" 緩存中 key = e.organizationId 的條目↓
下次調用 averageSalary(e.orgId) → 緩存失效 → 重新查數據庫計算
? 七、最佳實踐建議
- 緩存名要語義化:如
"userProfile"
,"productCatalog"
- 合理設置過期時間:在
CacheConfiguration
中設置setExpiryPolicyFactory(...)
- 及時清理緩存:數據變更時用
@CacheEvict
- 避免緩存雪崩:給緩存設置隨機過期時間
- 監控緩存命中率:通過 Ignite Visor 或 Metrics 判斷緩存是否有效
🧩 八、Java 配置方式(替代 XML)
如果你用的是 Spring Boot 或 Java Config:
@Configuration
@EnableCaching
public class IgniteCacheConfig {@Beanpublic Ignite igniteInstance() {IgniteConfiguration cfg = new IgniteConfiguration();cfg.setIgniteInstanceName("myIgnite");cfg.setPeerClassLoadingEnabled(true);return Ignition.start(cfg);}@Beanpublic CacheManager cacheManager() {SpringCacheManager cacheManager = new SpringCacheManager();cacheManager.setGridName("myIgnite"); // 關聯上面的節點return cacheManager;}
}
🎯 九、一句話總結
Apache Ignite 通過
SpringCacheManager
實現了 Spring Cache 抽象,讓你可以用@Cacheable
、@CacheEvict
等注解,自動將耗時方法的結果緩存到 Ignite 分布式緩存中,從而大幅提升性能、降低數據庫負載,特別適合緩存數據庫查詢、遠程調用等場景。
🔄 十、和 Spring Data 的關系(終極總結)
場景 | 用哪個? |
---|---|
我想把某個方法的結果緩存起來,避免重復執行 | ? Spring Cache + @Cacheable |
我想直接操作 Ignite 緩存中的數據(增刪改查) | ? Spring Data + IgniteRepository |
我既有復雜查詢,又想緩存結果 | ? 兩者結合使用! ? 用 Spring Data 操作緩存 ? 用 Spring Cache 緩存高頻查詢結果 |
需要我為你生成一個完整的 Spring Boot + Ignite Cache 示例項目嗎?包括配置、實體、Service 和測試用例。歡迎繼續提問 😊