导读:本期聚焦于小师妹创作的《如何在 Spring Boot 中整合 Spring Data GemFire 实现分布式缓存?》,敬请观看详情。把本地缓存替换为 GemFire 前需要先理解,它不是 Redis 的简单平替,而是一套带 Region 分区、PDX 序列化与位置透明的分布式数据平台。Spring Data GemFire 将这套能力包装成熟悉的 Spring Cache 注解,开发者可以在不修改大量业务代码的前提下接入缓存。本文从 GemFire 服务端准备、项目依赖、ClientCache 配置和常见调优点几个角度,给出一个能够直接落地的整合方案。文中会以 Customer 实体为例,演示如何通过 ClientCacheApplication 连接 Locator,如何让 Cacheable 自动创建 Region,以及如何避免键序列化和 CacheManager 冲突等问题。即使你熟悉 Redis,也建议关注 GemFire 在强一致分区与缓存事务上的差异,这对金融、交易类系统尤其重要。

Spring Boot 内置的缓存抽象只提供了本地实现,比如 ConcurrentMapCacheManager,应用一旦部署多个实例,缓存命中率会下降,数据也可能互相覆盖。GemFire 作为 VMware 的分布式内存数据网格,可以通过 Spring Data GemFire 接入 Spring Cache 抽象,使 @Cacheable、@CachePut、@CacheEvict 直接管理远端 Region。本文以一个客户查询服务为例,说明从依赖到配置再到缓存读写的完整整合方式。

如何在 Spring Boot 中整合 Spring Data GemFire 实现分布式缓存?

一、准备 GemFire 环境与项目依赖

GemFire 的最小部署通常包含 Locator 和 Server 两种角色。Locator 负责服务发现、负载均衡和成员管理,Server 承载真实的数据 Region。开发环境可以使用 gfsh 命令行快速拉起一个单节点集群,命令如下。

start locator --name=locator1 --port=10334
start server --name=server1 --locators=localhost[10334]
create region --name=Customers --type=PARTITION_REDUNDANT --redundant-copies=1

在 Spring Boot 项目中接入 GemFire,最简单的方式是引入 spring-geode-starter。它会把 Spring Data GemFire 以及客户端缓存自动配置一并带入,减少手工装配 ClientCache 的成本。Maven 依赖如下。

<dependency>
    <groupId>org.springframework.geode</groupId>
    <artifactId>spring-geode-starter</artifactId>
</dependency>

版本方面,如果项目已经通过 Spring Boot BOM 统一管理依赖,可以不再单独指定版本号。但要注意不同版本的 Spring Data GemFire 对 GemFire 服务端版本有对应要求,升级前应先核对兼容矩阵,避免客户端连接不上旧版 Locator。若项目同时引入了 Redis 或 Caffeine 缓存组件,还需要排除它们自动配置的 CacheManager,避免运行时出现多个缓存管理器冲突。

二、配置 ClientCache 与 Region

主类上通过 @ClientCacheApplication 注解连接 Locator,这是 Spring Data GemFire 提供的客户端缓存声明式配置。它会在应用启动时创建一个 ClientCache 实例,并自动连接指定的 Locator 地址。与手工使用 ClientCacheFactory 相比,注解方式更适合 Spring Boot 的自动装配风格。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.config.annotation.EnableCachingDefinedRegions;
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
import org.springframework.data.gemfire.config.annotation.Locator;

@SpringBootApplication
@ClientCacheApplication(name = "GemFireClientCache", locators = @Locator(host = "localhost", port = 10334))
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
@EnableCachingDefinedRegions
public class GemFireCacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(GemFireCacheApplication.class, args);
    }
}

上面的配置里,@EnableEntityDefinedRegions 会扫描标记了 @Region 的实体类并自动创建对应 Region,@EnableCachingDefinedRegions 则根据 Spring Cache 注解中的 value 创建缓存 Region。Customer 实体可以这样定义。

import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.annotation.Region;

@Region("Customers")
public class Customer {

    @Id
    private String id;
    private String name;

    public Customer() {
    }

    public Customer(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

如果 Region 已经在服务端通过 gfsh 手动创建,则要保证 Region 名称与 @Cacheable(value = "Customers") 中的 value 完全一致。对于自动创建 Region 的方式,应用启动时客户端会向 Locator 发送 Region 创建请求,因此运行前需要确保 Locator 和 Server 已经可用。

三、使用 Spring Cache 注解完成读写

接入 GemFire 之后,Service 层仍然使用标准 Spring Cache 注解,不需要直接操作 GemFire 的 API。以下示例展示了查询方法如何通过 @Cacheable 先读缓存,未命中时再查询数据库或模拟慢查询。

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class CustomerService {

    @Cacheable(value = "Customers", key = "#id", unless = "#result == null")
    public Customer getCustomer(String id) {
        simulateSlowService(id);
        Customer customer = new Customer();
        customer.setId(id);
        customer.setName("name-" + id);
        return customer;
    }

    private void simulateSlowService(String id) {
        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

这里的 key 表达式 #id 表示使用方法参数作为 Region 的键,unless 条件可以阻止 null 结果写入缓存,减少缓存穿透风险。首次调用 getCustomer 会执行方法体并把返回结果写入 GemFire 的 Customers Region,后续相同 id 的请求会直接命中远端缓存,不再进入方法体。

如果数据发生更新,需要使用 @CacheEvict 清除旧缓存,或者使用 @CachePut 不跳过方法执行直接更新缓存。下面给出 @CacheEvict 的简单示例。

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class CustomerService {

    @Cacheable(value = "Customers", key = "#id")
    public Customer getCustomer(String id) {
        return queryFromDatabase(id);
    }

    @CacheEvict(value = "Customers", key = "#customer.id")
    public Customer updateCustomer(Customer customer) {
        return saveToDatabase(customer);
    }

    private Customer queryFromDatabase(String id) {
        Customer customer = new Customer();
        customer.setId(id);
        customer.setName("name-" + id);
        return customer;
    }

    private Customer saveToDatabase(Customer customer) {
        return customer;
    }
}

使用 @CachePut 时要注意,方法始终会执行,并且返回值会写入缓存。如果更新方法本身需要返回最新数据,可以用它替代 @Cacheable 和 @CacheEvict 的组合。不过对于删除操作,仍然只能使用 @CacheEvict,因为它没有返回数据可以写入缓存。

四、序列化、分区与常见问题

GemFire 推荐使用 PDX 序列化而不是原生 Java 序列化。启用 @EnablePdx 后,对象会以字段结构存储,查询时无需反序列化整个对象,也具备更好的版本兼容性。配置方式很简单,只需新建一个配置类。

import org.springframework.context.annotation.Configuration;
import org.springframework.data.gemfire.config.annotation.EnablePdx;

@Configuration
@EnablePdx
public class GemFirePdxConfig {
}

默认情况下,Region 使用 PARTITION 类型在集群中进行分片,数据分布均匀但单份存储。如果对可用性要求较高,可以参考前文 gfsh 示例创建 PARTITION_REDUNDANT 类型并设置冗余副本数。冗余副本会增加内存占用和网络同步开销,因此需要结合实际数据规模评估,通常设置一份冗余即可满足多数场景。

实际项目中还有一个常见问题是键的序列化。使用 Spring Cache 注解时,方法参数会作为 GemFire Region 的键,键类型应尽量保持一致。比如不要在一次调用中传入 String,另一次传入 Long,否则可能因为序列化类型不同而导致缓存查找失败。同时要避免将大对象直接作为键,建议使用业务主键或可读性高的组合键。

从长期维护角度看,客户端连接池、Socket 缓冲区大小和 Region 过期策略都需要关注。GemFire 支持在 Region 上配置 TTL 和 TTI,可以在创建 Region 时通过 @EnableExpiration 或自定义 RegionConfigurer 完成。最后,监控缓存命中率、服务端 Region 大小以及客户端连接数,能够帮助你及时发现缓存穿透、热点数据和客户端资源泄漏等问题。

Spring BootSpring Data GemFire分布式缓存修改时间:2026-09-22 03:02:32

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0922/60305.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。