PostgreSQL’s streaming replication is a feature that allows continuous, mirrored replication of a live database to one or more standby servers. The architecture of PostgreSQL’s streaming replication consists of two main components: the primary server and the standby servers.
The primary server is the live database server that accepts client connections and processes write transactions. The primary server continuously streams its write-ahead logs (WALs) to the standby servers where they are applied to the standby’s database. The WALs are a sequence of log records that contain the changes made to the database by each transaction.
The standby servers are replicas of the primary server that continuously receive and apply the WALs to their own database. They are in a "hot standby" mode, meaning they can accept read-only queries from clients. If the primary server fails, one of the standby servers can be promoted to become the new primary server and continue serving clients. This feature provides a robust and fault-tolerant solution for high availability.
PostgreSQL’s streaming replication can be extended and customized for specific use cases using the following methods:
1. Logical Replication: This feature allows individual tables or subsets of a database to be replicated to other databases. Logical replication is preferable when fine-grained control is required for replicating certain subsets of data. It involves the use of replication slots and a replication protocol to move data between servers.
2. Batch Streaming Replication: Introduces a batch mode that enables batched streaming of WALs between master and standby servers. In this mode, the replication stream is split into packets and can be more efficiently transferred over slow or unreliable networks.
3. Multi-master Replication: PostgreSQL also supports multi-master replication where two or more nodes coordinate to accept read/write transactions, and each node replicates changes made by the other nodes. Multi-master replication allows for distributed systems where there is no single node that needs to be trusted with updates.
4. Replication Slots: PostgreSQL’s replication slots provide a way to maintain a consistent state for standby servers by keeping track of the WALs that have already been processed. Replication slots ensure that old WALs are not recycled, ensuring that standby servers will be able to catch up to the primary server when they have been disconnected.
5. Custom Recovery: PostgreSQL’s recovery process can be customized in several ways such as specifying which WAL files to restore from the archive, running additional scripts before and after recovery, and changing the settings for the new primary server. Custom recovery allows different types of recovery scenarios to be implemented and customized according to specific requirements.
Here’s an example of how to set up a streaming replication in Java, using the PostgreSQL JDBC driver:
public class ReplicationSetup {
public static void main(String[] args) {
String primaryUrl = "jdbc:postgresql://primary-server/db";
String standbyUrl = "jdbc:postgresql://standby-server/db";
Properties props = new Properties();
props.setProperty("user", "username");
props.setProperty("password", "password");
try(Connection primaryConn = DriverManager.getConnection(primaryUrl, props);
Statement primaryStmt = primaryConn.createStatement();) {
// enable WAL archiving on primary server
primaryStmt.execute("ALTER SYSTEM SET wal_level = replica");
primaryStmt.execute("ALTER SYSTEM SET archive_mode = on");
primaryStmt.execute("ALTER SYSTEM SET archive_command = 'rsync %p /pgdata/wal_archive/%f'");
primaryStmt.execute("SELECT pg_reload_conf()");
// create a replication user on primary server
primaryStmt.execute("CREATE USER replication WITH REPLICATION PASSWORD 'password'");
// create a replication slot on primary server
primaryStmt.execute("SELECT * FROM pg_create_physical_replication_slot('standby_slot')");
// create a replication configuration file on standby server
String configFile = "/pgdata/postgresql.conf";
Files.write(Paths.get(configFile), Arrays.asList(
"primary_conninfo = 'host=primary-server user=replication password=password'",
"standby_mode = 'on'",
"primary_slot_name = 'standby_slot'"
));
// start the standby server
ProcessBuilder pb = new ProcessBuilder("pg_ctl", "-D", "/pgdata", "start");
pb.redirectErrorStream(true);
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.start();
} catch (SQLException | IOException ex) {
ex.printStackTrace();
}
}
}
In this example, we set up WAL archiving on the primary server, create a replication user and slot, and create a configuration file on the standby server. Finally, we start the standby server, which will start replicating changes from the primary server. This is just a basic example; in practice, additional configuration and monitoring steps would be required to ensure robust and efficient replication.