1. 概述

GemFire 是一款高性能分布式数据管理基础设施,位于应用集群和后端数据源之间。通过内存化数据管理,GemFire 能显著提升访问速度。Spring Data 提供了从 Spring 应用中轻松配置和访问 GemFire 的能力

本文将探讨如何利用 GemFire 满足应用的缓存需求。

⚠️ 重要更新Spring Data GemFire 项目所有权已从 Spring 团队转移至 VMware 的 GemFire 团队。现在应使用 Spring Data for VMware GemFire 项目。

功能基本相同,但依赖的 groupId、artifactId、版本和 Maven 仓库已变更。如何添加更新依赖请参考官方文档

2. Maven 依赖

要启用 Spring Data GemFire 支持,需在 pom.xml 中添加以下依赖:

<dependency>
    <groupId>com.vmware.gemfire</groupId>
    <artifactId>spring-data-gemfire</artifactId>
    <version>2.7.0</version>
</dependency>

最新版本可在 Maven Central 查询。

3. GemFire 核心特性

3.1. 缓存 (Cache)

GemFire 的缓存提供基础数据管理服务,并管理与其他节点的连接。缓存配置文件 (cache.xml) 描述了数据在不同节点间的分布方式:

<cache>
    <region name="region">
        <region-attributes>
            <cache-listener>
                <class-name>
                com.example.CacheListenerImpl
                </class-name>
            </cache-listener>
        </region-attributes>
    </region>
    ...
</cache>

3.2. 区域 (Regions)

数据区域是缓存中逻辑上的数据分组。简单说,区域允许我们在系统多个 JVM 中存储数据,而无需关心数据具体存储在集群哪个节点

区域分为三类:

  • **复制区域 (Replicated region)**:每个节点存储完整数据副本。读性能极高,写操作较慢(需同步所有节点):
    <region name="myRegion" refid="REPLICATE"/>
    
  • **分区区域 (Partitioned region)**:数据分散存储,每个节点只保存部分数据。写性能优异:
    <region name="myRegion" refid="PARTITION"/>
    
  • **本地区域 (Local region)**:仅存在于定义节点,无集群连接:
    <region name="myRegion" refid="LOCAL"/>
    

3.3. 缓存查询

GemFire 提供 OQL(对象查询语言)语法类似 SQL。基础查询示例:

SELECT DISTINCT * FROM exampleRegion

通过 QueryService 创建查询对象执行 OQL。

3.4. 数据序列化

为提升性能,GemFire 提供优于 Java 序列化的方案:

  • ✅ 跨语言支持
  • ✅ 更高的序列化/反序列化速度
  • ✅ 灵活的数据存储格式

核心方案是 **PDX (Portable Data eXchange)**:通过命名字段存储数据,支持直接访问字段而无需完全反序列化对象。

3.5. 函数执行

GemFire 允许函数驻留在服务器端,客户端或其他服务器可直接调用,无需传输函数代码。调用者可指定:

  • 数据依赖函数在特定数据集执行
  • 独立数据函数在特定服务器/成员/成员组执行

3.6. 连续查询 (Continuous Querying)

客户端通过 SQL 类型的查询过滤器订阅服务端事件。服务端将所有修改查询结果的事件推送给客户端。示例查询:

SELECT * from StockRegion s where s.stockStatus='active';

要获取此查询的状态更新,需在 StockRegion 附加 CQListener 实现:

<cache>
    <region name="StockRegion">
        <region-attributes refid="REPLICATE">
            ...
            <cache-listener>
                <class-name>com.example.StockListener</class-name>
            </cache-listener>
        ...
        </region-attributes>
    </region>
</cache>

4. Spring Data GemFire 支持

4.1. Java 配置

Spring Data GemFire 提供注解简化配置:

@Configuration
public class GemfireConfiguration {

    @Bean
    Properties gemfireProperties() {
        Properties gemfireProperties = new Properties();
        gemfireProperties.setProperty("name", "SpringDataGemFireApplication");
        gemfireProperties.setProperty("mcast-port", "0"); // 禁用多播发现
        gemfireProperties.setProperty("log-level", "config");
        return gemfireProperties;
    }

    @Bean
    CacheFactoryBean gemfireCache() {
        CacheFactoryBean gemfireCache = new CacheFactoryBean();
        gemfireCache.setClose(true);
        gemfireCache.setProperties(gemfireProperties());
        return gemfireCache;
    }

    @Bean(name="employee")
    LocalRegionFactoryBean<String, Employee> getEmployee(final GemFireCache cache) {
        LocalRegionFactoryBean<String, Employee> employeeRegion = new LocalRegionFactoryBean<>();
        employeeRegion.setCache(cache);
        employeeRegion.setName("employee");
        return employeeRegion;
    }
}

关键点:

  • mcast-port=0 表示禁用多播发现
  • 通过 CacheFactoryBean 创建 GemFireCache 实例
  • 使用 LocalRegionFactoryBean 创建 Employee 实例的存储区域

4.2. 实体映射

通过注解定义对象到 GemFire 网格的映射:

@Region("employee")
public class Employee {

    @Id
    public String name;
    public double salary;

    @PersistenceConstructor
    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    // 标准getter/setter
}

注解说明:

  • @Region:指定实体存储的区域
  • @Id:标记作为缓存键的属性
  • @PersistenceConstructor:标记用于创建实体的构造函数(多构造函数时必需)

4.3. GemFire 仓库

启用仓库支持的核心配置:

@Configuration
@EnableGemfireRepositories(basePackages 
  = "com.baeldung.spring.data.gemfire.repository")
public class GemfireConfiguration {

    @Autowired
    EmployeeRepository employeeRepository;
    
    // ...
}

4.4. OQL 查询支持

仓库接口支持定义 OQL 查询方法:

@Repository
public interface EmployeeRepository extends   
  CrudRepository<Employee, String> {

    Employee findByName(String name);

    Iterable<Employee> findBySalaryGreaterThan(double salary);

    Iterable<Employee> findBySalaryLessThan(double salary);

    Iterable<Employee> 
      findBySalaryGreaterThanAndSalaryLessThan(double salary1, double salary2);
}

4.5. 函数执行支持

通过注解简化函数操作:

函数实现

@Component
public class FunctionImpl {

    @GemfireFunction
    public void greeting(String message){
        // 业务逻辑
    }
 
    // ...
}

启用函数注解处理:

@Configuration
@EnableGemfireFunctions
public class GemfireConfiguration {
    // ...
}

函数执行

@OnRegion(region="employee")
public interface FunctionExecution {
 
    @FunctionId("greeting")
    public void execute(String message);
    
    // ...
}

启用执行注解处理:

@Configuration
@EnableGemfireFunctionExecutions(
  basePackages = "com.baeldung.spring.data.gemfire.function")
public class GemfireConfiguration {
    // ...
}

5. 总结

本文探索了 GemFire 的核心特性,并展示了 Spring Data 如何简化其使用。关键收获:

  • ✅ 三种区域类型满足不同场景需求
  • ✅ PDX 序列化提升性能
  • ✅ 连续查询实现实时数据推送
  • ✅ Spring 注解大幅简化配置

完整代码示例见 GitHub 仓库


原始标题:A Guide to GemFire with Spring Data