Spring Data JPA:如何对 RDS Aurora PostgreSQL 实例之间的读取查询进行负载平衡?

Posted

技术标签:

【中文标题】Spring Data JPA:如何对 RDS Aurora PostgreSQL 实例之间的读取查询进行负载平衡?【英文标题】:Spring Data JPA: How to load balance read queries between RDS Aurora PostgreSQL instances? 【发布时间】:2019-10-23 05:02:38 【问题描述】:

我在 AWS 中创建了一个 Aurora PostgreSQL 集群:

+ mydb (Role: Regional), (Engine: Aurora PostgreSQL), (Region and AZ: ap-southeast-2)
|
+- foo (Role: Writer),   (Engine: Aurora PostgreSQL), (Region and AZ: ap-southeast-2a), Multi-AZ (2 Zones)
|
+- bar (Role: Reader),   (Engine: Aurora PostgreSQL), (Region and AZ: ap-southeast-2b), Multi-AZ (2 Zones)

Writer 实例有一个端点,Reader 实例有一个端点:

| Endpoint name                                         | Type   |
|-------------------------------------------------------|--------|
| mydb.cluster-1234.ap-southeast-2.rds.amazonaws.com    | Writer |
| mydb.cluster-ro-1234.ap-southeast-2.rds.amazonaws.com | Reader |

在我的应用程序中,我像往常一样定义了一个数据源:

spring:
  datasource:
    url: jdbc:postgresql://mydb.cluster-1234.ap-southeast-2.rds.amazonaws.com:5432/someDb?currentSchema=someSchema
    username: someUser
    password: somePass

同样,代码中定义了一些普通的实体和存储库:

public interface ThingRepository extends JpaRepository<Thing, Long> 


@Entity
public class Thing 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Basic
    private String name;

    // etc.

同样,还有一些普通的 READ/WRITE 操作:

public void doSomething() 
    Thing thing = thingRepository.findById(123L);
    // ...


public void doSomethingElse() 
    Thing thing = new Thing();
    thingRepository.save(thing);
    // ...

问题是所有这些查询都被发送到 Aurora 的 Writer 实例,而我的 Reader 实例仍未使用。

但我希望方法调用(例如 findByIdexistsByIdfindAll 等)在我的集群中的所有实例之间进行负载平衡,并且只需要 savesaveAll、@987654331 等操作@, deleteAll 发送到 Writer 实例。

有没有办法做到这一点?

【问题讨论】:

嗨 Behrang,有什么解决方案吗?我陷入了同样的问题 【参考方案1】:

您可以做的是设置两个数据源并使用不同的数据源创建不同的存储库。

使用 JPA,但这种方法存在一个问题:如果您读取一个实体并对其进行操作,它将被保存,这可能无法正常工作,并且至少在原始读取进入读取实例时是不希望的。

因此,为了防止这种情况发生,您必须在加载实体后将其分离,如果您不确定在分离之前完全加载实体,这又会导致 LazyLoadingException

【讨论】:

当一些实体在一个数据库中而另一些在另一个数据库中时创建两个数据源是有意义的。但是,如果您考虑一下,您提出的解决方案并不是那么优雅,而且我认为它也无法正常工作。至少它需要对代码进行重大更改。 我并不是说它很优雅。但是为什么你认为它不会“正常工作”。无论如何,我看到的唯一选择是编写自己的数据源,根据需要路由语句。【参考方案2】:

您尝试过使用Spring Cloud AWSData Access with JDBC# 吗?

它拥有使用只读副本配置连接到 Aurora 实例所需的一切

【讨论】:

以上是关于Spring Data JPA:如何对 RDS Aurora PostgreSQL 实例之间的读取查询进行负载平衡?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过分页在 Spring Data JPA 中的 SELECT 子句中按别名对投影进行排序?

如何使用 XML 配置 Spring Data JPA

如何在 Spring Boot / Spring Data 中为 Amazon RDS Mysql 启用 SSL?

Spring Data JPA中多数据源的配置

Spring Data Jpa: 分页和排序

Spring Data Jpa: 分页和排序