这份文档是关于 如何使用 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 {
@Bean
public Ignite igniteInstance() {
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setIgniteInstanceName("myIgnite");
cfg.setPeerClassLoadingEnabled(true);
return Ignition.start(cfg);
}
@Bean
public 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 和测试用例。欢迎继续提问 😊