当应用从单机走向多节点部署时,缓存方案的选择会直接影响系统的吞吐能力和数据一致性。本地缓存读写最快,但节点之间互不可见,容易出现脏数据;集中式缓存解决了共享问题,可高并发下网络往返和单点带宽又成了新的短板。Apache Ignite 把这两者的优点结合起来:它将数据以键值对形式分布在集群所有节点的堆外内存里,配合亲和性路由,读写请求可以直接打到数据所在的节点,延迟接近本地缓存,同时天然具备分布式的扩展能力。本文结合 Spring Boot,完整演示如何把 Ignite 接入到项目中,实现内存级的数据缓存与分布式计算。

一、Ignite 的内存架构与核心概念
在动手写代码之前,有必要先弄清 Ignite 的几个基本模型,否则配置参数时容易一头雾水。Ignite 的定位是内存为中心的分布式数据库,它的核心存储单元叫 Region,默认名字叫 defaultRegion。每个 Region 内部由若干 Segment 组成,Ignite 默认会按 CPU 核数分配 Segment 数量来减少锁竞争,实际使用中一般保持默认即可。
内存模型分为两部分:数据区和索引区。数据区存放的是缓存的键值对,每个缓存通过setDataRegionStorageMaxSize之类的配置绑定到某个数据区;索引区则统一存放 SQL 索引和哈希索引。这两个区域默认都开启可伸缩模式,数据量增长时内存页会按需分配,不必一开始就锁定大块内存。
Ignite 提供三种缓存模式:PARTITIONED是主推方式,数据按哈希分片打散到各节点,每个主分片可以配置若干副本保证高可用;REPLICATED模式则是每个节点都持有全量数据,读性能极高但写入成本大,适合字典类小数据;LOCAL模式退化为纯本地缓存,基本只在测试场景使用。理解这三种模式的取舍,是后面容量规划和一致性配置的基础。
二、引入依赖并完成基础配置
Spring Boot 官方并没有针对 Ignite 的 starter,需要手动引入 Ignite 的 Spring 集成包。以 Maven 项目为例,在 pom.xml 中加入以下依赖,版本建议选择 2.14 以上的稳定版,同时注意 Ignite 内部依赖的 Spring 版本要与 Spring Boot 保持兼容,避免类加载冲突:
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-spring-boot-ext</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId;gt;</artifactId>
</dependency>上面第二个依赖写错了示范,正确完整写法如下,核心是ignite-core与ignite-spring两个包:
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-core</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-spring</artifactId>
<version>2.15.0</version>
</dependency>接下来在配置类中创建 Ignite 实例。关键配置包括节点发现机制、数据区大小和缓存定义。单机调试时可以用静态 IP 列表做发现,生产环境建议接入 ZooKeeper 或者 Kubernetes 的 TCP 发现:
@Configuration
public class IgniteConfig {
@Bean
public Ignite igniteInstance() {
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setIgniteInstanceName("spring-boot-ignite-node");
// 节点发现:单机或小集群用静态 IP 列表即可
TcpDiscoverySpi spi = new TcpDiscoverySpi();
TcpDiscoveryVmIpFinder finder = new TcpDiscoveryVmIpFinder();
finder.setAddresses(Arrays.asList("127.0.0.1:47500..47509"));
spi.setIpFinder(finder);
cfg.setDiscoverySpi(spi);
// 数据区内存上限,默认堆外内存 20%,按需调整
DataStorageConfiguration storage = new DataStorageConfiguration();
storage.getDefaultDataRegionConfiguration()
.setMaxSize(512L * 1024 * 1024); // 512MB
cfg.setDataStorageConfiguration(storage);
return Ignition.start(cfg);
}
}这里有一个容易踩的坑:setMaxSize设置的是堆外内存上限,Ignite 默认不会预分配,而是随数据增长逐步申请。如果服务器物理内存紧张,一定要显式限制,否则可能触发操作系统的内存溢出保护把进程直接杀掉。
三、对接 Spring Cache 注解,让业务代码零侵入
Ignite 提供了SpringCacheManager,可以作为 Spring Cache 抽象层的实现,业务代码只要加@Cacheable、@CachePut等注解就能透明地读写 Ignite 集群。先在配置文件中声明缓存管理器:
@Bean
public SpringCacheManager cacheManager(Ignite ignite) {
SpringCacheManager manager = new SpringCacheManager();
manager.setConfigurationCacheName("app-cache-config");
return manager;
}然后在启动类上开启缓存注解,业务方法上的用法与本地缓存完全一致:
@SpringBootApplication
@EnableCaching
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@Service
public class UserService {
@Cacheable(cacheNames = "users", key = "#id")
public User getUserById(Long id) {
// 未命中缓存时才查库
return userMapper.selectById(id);
}
@CachePut(cacheNames = "users", key = "#user.id")
public User updateUser(User user) {
userMapper.updateById(user);
return user;
}
@CacheEvict(cacheNames = "users", key = "#id")
public void deleteUser(Long id) {
userMapper.deleteById(id);
}
}使用注解方式时有两点需要留意。第一,被缓存的对象必须可序列化,最简单的办法是让实体类实现Serializable接口,追求性能可以配置 BinaryMarshaller 用二进制协议序列化。第二,SpringCacheManager默认按需创建缓存,若想预定义缓存的分区数、副本数和过期策略,需要提前注册一个名称为ignite-cache-configuration的系统缓存,把各缓存的CacheConfiguration放进去,这样所有节点创建的缓存配置才能保持一致。
四、分布式计算与持久化补充
Ignite 不只是缓存,它还内置了分布式的计算能力。当数据已经分布在集群中时,把计算任务推送到数据所在的节点执行,比把数据拉回应用层再计算高效得多。下面这个例子演示了如何并行地对一批用户做服务端计算:
@Service
public class ComputeService {
@Autowired
private Ignite ignite;
public void computeScores(List<Long> userIds) {
IgniteCompute compute = ignite.compute();
// 按用户 ID 哈希路由到对应节点执行,避免数据搬迁
compute.affinityRun("users", userIds.get(0), () -> {
System.out.println("任务在数据所在节点执行");
});
// 广播任务到所有节点
compute.broadcast(() -> System.out.println("每个节点都会执行一次"));
}
}关于持久化,Ignite 支持开启原生持久化(Native Persistence),数据在写入内存页的同时异步刷盘,重启后可以直接从磁盘恢复,无需重新预热缓存。在DataStorageConfiguration中调用setPersistenceEnabled(true)即可开启,默认存储路径为ignite\work\db,可以通过setStoragePath调整。开启持久化后,每个数据区由内存页加磁盘 WAL 两部分组成,写入路径会略慢一些,但换来的是崩溃恢复能力,需要按业务对数据丢失的容忍度来权衡。
最后是集群部署的几个实践建议:节点间端口(默认 47100 通信端口和 47500 发现端口)要确保互相可达;时钟偏差要控制在一定范围内,否则节点可能被判定为拓扑异常而踢出集群;滚动升级时新旧节点的主次版本必须兼容,Ignite 对版本混搭的要求比较严格,升级前务必查阅对应版本的兼容性说明。把这些细节处理好,Spring Boot 与 Ignite 的组合就能在内存级读写性能和分布式扩展能力之间取得很好的平衡。
Spring BootApache Ignite分布式缓存修改时间:2026-09-12 11:00:49