使用Spring Data的GemFire指南

2023/05/18

1. 概述

GemFire是一个高性能的分布式数据管理基础设施,位于应用程序集群和后端数据源之间。

使用GemFire,可以在内存中管理数据,从而加快访问速度。Spring Data提供了一种从Spring应用程序轻松配置和访问GemFire的方法

在本文中,我们将了解如何使用GemFire来满足应用程序的缓存要求。

重要更新spring-data-gemfire项目的所有权已在VMware内部从Spring团队转移到GemFire团队。你现在可以使用Spring Data for VMware GemFire项目。

功能基本相同,但依赖项组ID、工件ID、版本和Maven仓库已更改。要了解如何将更新的依赖项添加到你的项目,请查看此处的指南。

2. Maven依赖

要使用Spring Data GemFire支持,我们首先需要在pom.xml中添加以下依赖项:

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-gemfire</artifactId>
    <version>1.9.1.RELEASE</version>
</dependency>

可以在此处找到此依赖项的最新版本。

3. GemFire基本功能

3.1 缓存

GemFire中的缓存提供基本的数据管理服务以及管理与其他对等点的连接。

缓存配置(cache.xml)描述了数据将如何在不同节点之间分布:

<cache>
    <region name="region">
        <region-attributes>
            <cache-listener>
                <class-name>
                    ...
                </class-name>
            </cache-listener>
        </region-attributes>
    </region>
    <!--...-->
</cache>

3.2 区域

数据区域是缓存中单个数据集的逻辑分组。

简单的说,区域可以让我们把数据存储在系统中的多个VM中,而不需要考虑数据存储在集群中的哪个节点上。

区域分为三大类:

  • 复制区域保存每个节点上的完整数据集。它提供了很高的读取性能。写入操作较慢,因为需要将数据更新传播到每个节点:

    <region name="myRegion" refid="REPLICATE"/>
    
  • 分区区域对数据进行分布,使得每个节点只存储一部分区域内容。数据的副本存储在其他节点之一上。它提供了良好的写入性能。

    <region name="myRegion" refid="PARTITION"/>
    
  • 本地区域驻留在定义成员节点上。与集群中的其他节点没有连接。

    <region name="myRegion" refid="LOCAL"/>
    

3.3 查询缓存

GemFire提供了一种称为OQL(对象查询语言)的查询语言,它允许我们引用存储在GemFire数据区域中的对象。这在语法上与SQL非常相似。让我们看看一个非常基本的查询是什么样的:

SELECT DISTINCT * FROM exampleRegion

GemFire的QueryService提供了创建查询对象的方法。

3.4 数据序列化

为了管理数据序列化-反序列化,GemFire提供了除Java序列化之外的选项,这些选项提供了更高的性能,为数据存储和数据传输提供了更大的灵活性,还支持不同的语言。

考虑到这一点,GemFire定义了便携式数据交换(PDX)数据格式。PDX是一种跨语言数据格式,它通过将数据存储在命名字段中来提供更快的序列化和反序列化,无需完全反序列化对象即可直接访问。

3.5 函数执行

在GemFire中,函数可以驻留在服务器上,并且可以从客户端应用程序或另一台服务器调用,而无需发送函数代码本身。

调用者可以指示依赖数据的函数对特定数据集进行操作,也可以引导独立数据函数对特定服务器、成员或成员组进行操作。

3.6 连续查询

通过连续查询,客户端通过使用SQL类型的查询过滤来订阅服务器端事件。服务器发送所有修改查询结果的事件。连续查询事件传递使用客户端/服务器订阅框架。

连续查询的语法类似于用OQL编写的基本查询。例如,提供来自Stock区域的最新股票数据的查询可以写成:

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

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

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

4. Spring Data GemFire支持

4.1 Java配置

为了简化配置,Spring Data GemFire提供了各种用于配置核心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;
    }
}

要设置GemFire缓存和区域,我们必须首先设置几个特定的属性。此处mcast-port设置为0,表示此GemFire节点已禁用多播发现和分发。然后将这些属性传递给CacheFactoryBean以创建GemFireCache实例。

使用GemFireCache bean,创建了一个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;
    }

    // standard getters/setters
}

在上面的示例中,我们使用了以下注解:

  • @Region,指定Employee类的区域实例
  • @Id,注解应用作缓存键的属性
  • @PersistenceConstructor,这有助于标记将用于创建实体的一个构造函数,以防多个构造函数可用

4.3 GemFire Repository

接下来,让我们看一下Spring Data中的一个核心组件-Repository:

@Configuration
@EnableGemfireRepositories(basePackages = "cn.tuyucheng.taketoday.spring.data.gemfire.repository")
public class GemfireConfiguration {

    @Autowired
    EmployeeRepository employeeRepository;

    // ...
}

4.4 Oql查询支持

Repository允许查询方法的定义,以针对托管实体映射到的区域有效地运行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 函数执行支持

我们还提供注解支持-以简化GemFire函数执行的工作。

当我们使用函数时,有两个问题需要解决,实现和执行。

让我们看看如何使用Spring Data注解将POJO公开为GemFire函数:

@Component
public class FunctionImpl {

    @GemfireFunction
    public void greeting(String message){
        // some logic
    }

    // ...
}

我们需要显式激活注解处理,@GemfireFunction才能工作:

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

对于函数执行,调用远程函数的进程需要提供调用参数、函数id、执行目标(onServer、onRegion、onMember等):

@OnRegion(region="employee")
public interface FunctionExecution {

    @FunctionId("greeting")
    void execute(String message);

    // ...
}

要启用函数执行注解处理,我们需要使用Spring的组件扫描功能添加激活它:

@Configuration
@EnableGemfireFunctionExecutions(basePackages = "cn.tuyucheng.taketoday.spring.data.gemfire.function")
public class GemfireConfiguration {
    // ...
}

5. 总结

在本文中,我们探讨了GemFire的基本功能,并研究了Spring Data提供的API如何使其易于使用。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章