

# 为 RDS for PostgreSQL 数据库实例设置主动-主动复制
设置主动-主动复制

以下过程说明如何在 `pgactive` 可用的两个 RDS for PostgreSQL 数据库实例之间启动主动-主动复制。要运行多区域高可用性示例，您需要在两个不同的区域中部署 Amazon RDS for PostgreSQL 实例，并设置 VPC 对等。有关更多信息，请参阅 [VPC 对等](https://docs.amazonaws.cn/vpc/latest/peering/what-is-vpc-peering.html)。

**注意**  
在多个区域之间发送流量可能会产生额外费用。

这些步骤假定已使用 `pgactive` 扩展启用 RDS for PostgreSQL 数据库实例。有关更多信息，请参阅 [初始化 pgactive 扩展功能](Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.md)。

**使用 `pgactive` 扩展配置第一个 RDS for PostgreSQL 数据库实例**

以下示例说明如何创建 `pgactive` 组，以及在 RDS for PostgreSQL 数据库实例上创建 `pgactive` 扩展所需的其它步骤。

1. 使用 `psql` 或其它客户端工具连接第一个 RDS for PostgreSQL 数据库实例。

   ```
   psql --host=firstinstance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password=PASSWORD --dbname=postgres
   ```

1. 使用以下命令在 RDS for PostgreSQL 实例上创建数据库：

   ```
   postgres=> CREATE DATABASE app;
   ```

1. 使用以下命令将连接切换到新数据库：

   ```
   \c app
   ```

1. 使用以下 SQL 语句创建并填充示例表：

   1. 使用以下 SQL 语句创建一个示例表。

      ```
      app=> CREATE SCHEMA inventory;
      CREATE TABLE inventory.products (
      id int PRIMARY KEY, product_name text NOT NULL,
      created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP);
      ```

   1. 使用以下 SQL 语句用一些示例数据填充表。

      ```
      app=> INSERT INTO inventory.products (id, product_name)
      VALUES (1, 'soap'), (2, 'shampoo'), (3, 'conditioner');
      ```

   1. 使用以下 SQL 语句验证表中是否存在数据。

      ```
       app=>SELECT count(*) FROM inventory.products;
      
       count
      -------
       3
      ```

1. 在现有数据库上创建 `pgactive` 扩展。

   ```
   app=> CREATE EXTENSION pgactive;
   ```

1. 要安全地创建并初始化 pgactive 组，请使用以下命令：

   ```
   app=>
   -- connection info for endpoint1
   CREATE SERVER pgactive_server_endpoint1
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint1>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint1
       OPTIONS (user 'postgres', password '<password>');
         -- connection info for endpoint2
   CREATE SERVER pgactive_server_endpoint2
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint2>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint2
       OPTIONS (user 'postgres', password '<password>');
   ```

   现在，您可以初始化复制组并添加此第一个实例：

   ```
   SELECT pgactive.pgactive_create_group(
       node_name := 'endpoint1-app',
       node_dsn := 'user_mapping=postgres pgactive_foreign_server=pgactive_server_endpoint1'
   
   );
   ```

   使用以下命令作为替代方案（安全性较低）来创建并初始化 pgactive 组：

   ```
   app=> SELECT pgactive.pgactive_create_group(
       node_name := 'node1-app',
       node_dsn := 'dbname=app host=firstinstance.111122223333.aws-region.rds.amazonaws.com user=postgres password=PASSWORD');
   ```

   node1-app 是您分配的名称，用于唯一标识 `pgactive` 组中的节点。
**注意**  
要在可公开访问的数据库实例上成功执行此步骤，必须通过将 `rds.custom_dns_resolution` 参数设置为 `1` 将其开启。

1. 要检查数据库实例是否就绪，请使用以下命令：

   ```
   app=> SELECT pgactive.pgactive_wait_for_node_ready();
   ```

   如果命令成功，您可以看到以下输出：

   ```
   pgactive_wait_for_node_ready 
   ------------------------------ 
   (1 row)
   ```

**配置第二个 RDS for PostgreSQL 实例并将其加入 `pgactive` 组**

以下示例说明如何将 RDS for PostgreSQL 数据库实例加入 `pgactive` 组，以及在数据库实例上创建 `pgactive` 扩展所需的其它步骤。

这些步骤假设已使用 `pgactive` 扩展设置了其它 RDS for PostgreSQL 数据库实例。有关更多信息，请参阅 [初始化 pgactive 扩展功能](Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.md)。

1. 使用 `psql` 连接到要从发布者接收更新的实例。

   ```
   psql --host=secondinstance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password=PASSWORD --dbname=postgres
   ```

1. 使用以下命令在第二个 RDS for PostgreSQL 数据库实例上创建数据库：

   ```
   postgres=> CREATE DATABASE app;
   ```

1. 使用以下命令将连接切换到新数据库：

   ```
   \c app
   ```

1. 在现有数据库上创建 `pgactive` 扩展。

   ```
   app=> CREATE EXTENSION pgactive;
   ```

1. 使用以下命令以更安全的方式将 RDS for PostgreSQL 第二个数据库实例加入 `pgactive` 组：

   ```
   -- connection info for endpoint1
   CREATE SERVER pgactive_server_endpoint1
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint1>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint1
       OPTIONS (user 'postgres', password '<password>');
   
   -- connection info for endpoint2
   CREATE SERVER pgactive_server_endpoint2
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint2>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint2
       OPTIONS (user 'postgres', password '<password>');
   ```

   ```
   SELECT pgactive.pgactive_join_group(
       node_name := 'endpoint2-app',
       node_dsn := 'user_mapping=postgres pgactive_foreign_server=pgactive_server_endpoint2',
       join_using_dsn := 'user_mapping=postgres pgactive_foreign_server=pgactive_server_endpoint1'
   );
   ```

   使用以下命令作为替代方案（安全性较低）将 RDS for PostgreSQL 第二个数据库实例加入 `pgactive` 组

   ```
   app=> SELECT pgactive.pgactive_join_group(
   node_name := 'node2-app',
   node_dsn := 'dbname=app host=secondinstance.111122223333.aws-region.rds.amazonaws.com user=postgres password=PASSWORD',
   join_using_dsn := 'dbname=app host=firstinstance.111122223333.aws-region.rds.amazonaws.com user=postgres password=PASSWORD');
   ```

   node2-app 是您分配的名称，用于唯一标识 `pgactive` 组中的节点。

1. 要检查数据库实例是否就绪，请使用以下命令：

   ```
   app=> SELECT pgactive.pgactive_wait_for_node_ready(); 
   ```

   如果命令成功，您可以看到以下输出：

   ```
   pgactive_wait_for_node_ready 
   ------------------------------ 
   (1 row)
   ```

   如果第一个 RDS for PostgreSQL 数据库相对较大，则可以看到 `pgactive.pgactive_wait_for_node_ready()` 正在发出还原操作的进度报告。输出看上去类似于以下内容：

   ```
   NOTICE:  restoring database 'app', 6% of 7483 MB complete
   NOTICE:  restoring database 'app', 42% of 7483 MB complete
   NOTICE:  restoring database 'app', 77% of 7483 MB complete
   NOTICE:  restoring database 'app', 98% of 7483 MB complete
   NOTICE:  successfully restored database 'app' from node node1-app in 00:04:12.274956
    pgactive_wait_for_node_ready 
   ------------------------------ 
   (1 row)
   ```

   此后，`pgactive` 将在两个数据库实例之间同步数据。

1. 您可以使用以下命令来验证第二个数据库实例的数据库是否具有数据：

   ```
   app=> SELECT count(*) FROM inventory.products;
   ```

   如果数据成功同步，您将看到以下输出：

   ```
    count
   -------
    3
   ```

1. 运行以下命令插入新值：

   ```
   app=> INSERT INTO inventory.products (id, product_name) VALUES (4, 'lotion');
   ```

1. 连接到第一个数据库实例的数据库并运行以下查询：

   ```
   app=> SELECT count(*) FROM inventory.products;
   ```

   如果已初始化主动-主动复制，则输出类似于以下内容：

   ```
   count
   -------
    4
   ```

**从 `pgactive` 组中分离和移除数据库实例**

您可以使用以下步骤从 `pgactive` 组中分离和移除数据库实例：

1. 您可以使用以下命令将第二个数据库实例与第一个数据库实例分离：

   ```
   app=> SELECT * FROM pgactive.pgactive_detach_nodes(ARRAY[‘node2-app']);
   ```

1. 使用以下命令从第二个数据库实例中移除 `pgactive` 扩展：

   ```
   app=> SELECT * FROM pgactive.pgactive_remove();
   ```

   要强制移除此扩展，请执行以下操作：

   ```
   app=> SELECT * FROM pgactive.pgactive_remove(true);
   ```

1. 使用以下命令删除扩展：

   ```
   app=> DROP EXTENSION pgactive;
   ```