如何使用 Apache Ignite 作为 Spring 框架的缓存(Spring Cache)后端

这份文档是关于 如何使用 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 的核心思想

💡 目标:避免重复执行耗时的操作(如数据库查询、远程调用),直接从缓存中返回结果。

举个例子:

java 复制代码
@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 包含:

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 节点
xml 复制代码
<bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager">
    <!-- 指定 Ignite 配置文件路径 -->
    <property name="configurationPath" value="config/ignite-config.xml"/>
</bean>

<!-- 启用注解驱动的缓存 -->
<cache:annotation-driven/>
方式二:使用已存在的 Ignite 节点(推荐集群环境)
xml 复制代码
<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自动创建它

自定义动态缓存配置

你可以设置默认的缓存模板:

xml 复制代码
<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 ------ 缓存方法结果

java 复制代码
@Cacheable("averageSalary")  // 缓存名为 "averageSalary"
public long averageSalary(int organizationId) {
    // 耗时操作:查数据库
    return jdbc.queryForObject("SELECT AVG(salary)...", Long.class, organizationId);
}
  • key 生成规则 :默认使用所有参数做 key(这里就是 organizationId
  • 效果:相同参数只执行一次,后续直接返回缓存

2. @CacheEvict ------ 删除缓存(数据变更时用)

java 复制代码
@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) → 缓存失效 → 重新查数据库计算

✅ 七、最佳实践建议

  1. 缓存名要语义化 :如 "userProfile", "productCatalog"
  2. 合理设置过期时间 :在 CacheConfiguration 中设置 setExpiryPolicyFactory(...)
  3. 及时清理缓存 :数据变更时用 @CacheEvict
  4. 避免缓存雪崩:给缓存设置随机过期时间
  5. 监控缓存命中率:通过 Ignite Visor 或 Metrics 判断缓存是否有效

🧩 八、Java 配置方式(替代 XML)

如果你用的是 Spring Boot 或 Java Config:

java 复制代码
@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 和测试用例。欢迎继续提问 😊

相关推荐
风向决定发型丶1 天前
redis集群搭建
数据库·redis·缓存
TanYYF1 天前
spring ai入门教程二
java·人工智能·spring
SeeYa-J1 天前
Spring IOC(Inversion of Control)
java·spring·rpc
宠友信息1 天前
多端数据互通场景下Spring Boot仿小红书源码结构设计
数据库·spring boot·redis·缓存·架构
长不胖的路人甲1 天前
Redis 缓存的数据持久化方案讲解
数据库·redis·缓存
长不胖的路人甲1 天前
Redis 单线程为什么速度很快
数据库·redis·缓存
长不胖的路人甲1 天前
Redis 数据删除策略
数据库·redis·spring
Flittly2 天前
【AgentScope Java新手村系列】(17)长期记忆系统
java·spring boot·spring
从此以后自律2 天前
Spring 全家桶
java·后端·spring
CCPC不拿奖不改名2 天前
Redis 工程化部署深度解析
linux·服务器·数据库·redis·深度学习·缓存·rag