Setting up active-active replication for RDS for PostgreSQL DB instances
The following procedure shows you how to start active-active replication between two
RDS for PostgreSQL DB instances where pgactive is available. To run the
multi-region high availability example, you need to deploy Amazon RDS for PostgreSQL instances
in two different regions and set up VPC Peering. For more information, see VPC
peering.
Note
Sending traffic between multiple regions may incur additional costs.
These steps assume that the RDS for PostgreSQL DB instance has been enabled with the
pgactive extension. For more information, see Initializing the
pgactive extension capability.
To configure the first RDS for PostgreSQL DB instance with the pgactive
extension
The following example illustrates how the pgactive group is created, along
with other steps required to create the pgactive extension on the RDS for PostgreSQL
DB instance.
-
Use
psqlor another client tool to connect to your first RDS for PostgreSQL DB instance.psql --host=firstinstance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres--password=PASSWORD--dbname=postgres -
Create a database on the RDS for PostgreSQL instance using the following command:
postgres=>CREATE DATABASEapp; -
Switch connection to the new database using the following command:
\capp -
Create and populate a sample table using the following SQL statements:
-
Create an example table using the following SQL statement.
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); -
Populate the table with some sample data by using the following SQL statement.
app=>INSERT INTO inventory.products (id, product_name) VALUES (1, 'soap'), (2, 'shampoo'), (3, 'conditioner'); -
Verify that data exists in the table by using the following SQL statement.
app=>SELECT count(*) FROM inventory.products;count ------- 3
-
-
Create
pgactiveextension on the existing database.app=>CREATE EXTENSION pgactive; -
To securely create and initialize the pgactive group use the following commands:
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>');Now you can initialize the replication group and add this first instance:
SELECT pgactive.pgactive_create_group( node_name :='endpoint1-app', node_dsn := 'user_mapping=postgres pgactive_foreign_server=pgactive_server_endpoint1' );Use the following commands as an alternate but less secure method to create and initialize the pgactive group:
app=>SELECT pgactive.pgactive_create_group( node_name :='node1-app', node_dsn := 'dbname=apphost=firstinstance.111122223333.aws-region.rds.amazonaws.com user=postgrespassword=PASSWORD');node1-app is the name that you assign to uniquely identify a node in the
pgactivegroup.Note
To perform this step successfully on a DB instance that is publicly accessible, you must turn on the
rds.custom_dns_resolutionparameter by setting it to1. -
To check if the DB instance is ready, use the following command:
app=>SELECT pgactive.pgactive_wait_for_node_ready();If the command succeeds, you can see the following output:
pgactive_wait_for_node_ready ------------------------------ (1 row)
To configure the second RDS for PostgreSQL instance and join it to the pgactive
group
The following example illustrates how you can join an RDS for PostgreSQL DB instance to the
pgactive group, along with other steps that are required to create the
pgactive extension on the DB instance.
These steps assume that another
RDS for PostgreSQL DB instances has been set up with the
pgactive extension. For more information, see Initializing the
pgactive extension capability.
-
Use
psqlto connect to the instance that you want to receive updates from the publisher.psql --host=secondinstance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres--password=PASSWORD--dbname=postgres -
Create a database on the second RDS for PostgreSQL DB instance using the following command:
postgres=>CREATE DATABASEapp; -
Switch connection to the new database using the following command:
\capp -
Create the
pgactiveextension on the existing database.app=>CREATE EXTENSION pgactive; -
Join the RDS for PostgreSQL second DB instance to the
pgactivegroup in a more secure way using the following commands:-- 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' );Use the following commands as an alternate but less secure method to join the RDS for PostgreSQL second DB instance to the
pgactivegroupapp=>SELECT pgactive.pgactive_join_group( node_name :='node2-app', node_dsn := 'dbname=apphost=secondinstance.111122223333.aws-region.rds.amazonaws.com user=postgrespassword=PASSWORD', join_using_dsn := 'dbname=apphost=firstinstance.111122223333.aws-region.rds.amazonaws.com user=postgrespassword=PASSWORD');node2-app is the name that you assign to uniquely identify a node in the
pgactivegroup. -
To check if the DB instance is ready, use the following command:
app=>SELECT pgactive.pgactive_wait_for_node_ready();If the command succeeds, you can see the following output:
pgactive_wait_for_node_ready ------------------------------ (1 row)If the first RDS for PostgreSQL database is relatively large, you can see
pgactive.pgactive_wait_for_node_ready()emitting the progress report of the restore operation. The output looks similar to the following: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)From this point forward,
pgactivesynchronizes the data between the two DB instances. -
You can use the following command to verify if the database of the second DB instance has the data:
app=>SELECT count(*) FROM inventory.products;If the data is successfully synchronized, you’ll see the following output:
count ------- 3 -
Run the following command to insert new values:
app=>INSERT INTO inventory.products (id, product_name) VALUES (4, 'lotion'); -
Connect to the database of the first DB instance and run the following query:
app=>SELECT count(*) FROM inventory.products;If the active-active replication is initialized, the output is similar to the following:
count ------- 4
To detach and remove a DB instance from the pgactive group
You can detach and remove a DB instance from the pgactive group using these
steps:
-
You can detach the second DB instance from the first DB instance using the following command:
app=>SELECT * FROM pgactive.pgactive_detach_nodes(ARRAY[‘node2-app']); -
Remove the
pgactiveextension from the second DB instance using the following command:app=>SELECT * FROM pgactive.pgactive_remove();To forcefully remove the extension:
app=>SELECT * FROM pgactive.pgactive_remove(true); -
Drop the extension using the following command:
app=>DROP EXTENSION pgactive;