Uso de drivers de cliente para implementar failover e separação de leitura/gravação
Desde o PostgreSQL 10 (libpq.so.5.10), libpq suporta failover e separação de leitura/gravação e a Java Database Connectivity (JDBC) suporta separação de leitura/gravação, failover e balanceamento de carga.
Os drivers do cliente PostgreSQL são compatíveis com versões anteriores. Até mesmo instâncias do RDS for PostgreSQL 9.5 e 9.6 podem ser conectadas por meio do driver libpq da versão mais recente para implementar o failover.
Nesta seção, failover se refere ao failover de cargas de trabalho somente leitura.
- libpq é uma interface de programação de aplicações (API) C para o PostgreSQL. libpq é um conjunto de funções de biblioteca que permitem que programas clientes passem consultas para o servidor de back-end de PostgreSQL e recebam os resultados dessas consultas.
- JDBC é uma API usada em Java para definir como os programas clientes acessam os bancos de dados. No PostgreSQL, o JDBC suporta failover e balanceamento de carga.
Driver |
Separação de leitura/gravação |
Balanceamento de carga |
Failover |
---|---|---|---|
libpq |
√ |
× |
√ |
JDBC |
√ |
√ |
√ |
Usar libpq para failover e separação de leitura/gravação
Você pode usar funções de libpq para se conectar a vários bancos de dados. Se um banco de dados falhar, as cargas de trabalho serão alternadas automaticamente para outro banco de dados disponível.
postgresql://[user[:password]@][netloc][:port][,...][/dbname][?param1=value1&...]
Exemplo: conectar a uma instância primária do RDS for PostgreSQL e duas réplicas de leitura. As solicitações de leitura não falharão desde que haja pelo menos uma instância disponível.
postgres://<instance_ip>:<instance_port>,<instance_ip>:<instance_port>,<instance_ip>:<instance_port>/<database_name>?target_session_attrs=any
Parâmetro |
Descrição |
Exemplo de valor |
---|---|---|
<instance_ip> |
Endereço IP da instância de BD. |
Se você tentar acessar a instância de um ECS, defina instance_ip como o endereço IP flutuante exibido na página Basic Information da instância. Se você tentar acessar a instância por meio de um EIP, defina instance_ip como o EIP vinculado à instância. |
<instance_port> |
Porta do banco de dados da instância de banco de dados. |
Defina este parâmetro como a porta do banco de dados exibida na página Basic Information. Valor padrão: 5432 |
<database_name> |
Nome do banco de dados a ser conectado. |
O banco de dados de gerenciamento padrão é postgres. Você pode inserir o nome do banco de dados com base nos requisitos do local. |
target_session_attrs |
Tipo do banco de dados a ser conectado. |
|
Para obter detalhes sobre libpq e parâmetros relacionados, consulte Cadeias de conexão.
Você pode usar a função pg_is_in_recovery() na aplicação para determinar se o banco de dados conectado é uma instância primária (indicada por f) ou uma réplica de leitura para implementar a separação de leitura/gravação.
O seguinte é um exemplo de código Python (psycopg2 um wrapper para libpq):
// There will be security risks if the username and password used for authentication are directly written into code. Store the username and password in ciphertext in the configuration file or environment variables. // In this example, the username and password are stored in the environment variables. Before running this example, set environment variables EXAMPLE_USERNAME_ENV and EXAMPLE_PASSWORD_ENV as needed. import psycopg2 import os username = os.getenv("EXAMPLE_USERNAME_ENV") password = os.getenv("EXAMPLE_PASSWORD_ENV") conn = psycopg2.connect(database=<database_name>,host=<instance_ip>, user=username, password=password, port=<instance_port>, target_session_attrs="read-write") cur = conn.cursor() cur.execute("select pg_is_in_recovery()") row = cur.fetchone() print("recovery =", row[0])
Usar JDBC para failover e separação de leitura/gravação
Você pode definir vários bancos de dados (hosts e portas) no URL de conexão e separá-los com vírgulas (,). O JDBC tentará se conectar a eles em sequência até que a conexão seja bem sucedida. Se a conexão falhar, uma mensagem de erro será exibida.
jdbc:postgresql://node1,node2,node3/${database}?targetServerType=preferSecondary&loadBalanceHosts=true
Exemplo:
jdbc:postgresql://<instance_ip>:<instance_port>,<instance_ip>:<instance_port>,<instance_ip>:<instance_port>/<database_name>?targetServerType=preferSecondary&loadBalanceHosts=true
Para obter detalhes sobre o código Java, consulte Conexão a uma instância do RDS for PostgreSQL por meio de JDBC.
Parâmetro |
Descrição |
Exemplo de valor |
---|---|---|
targetServerType |
Tipo do banco de dados a ser conectado. |
|
loadBalanceHosts |
Sequência de bancos de dados a serem conectados. |
|
Para distinguir entre os bancos de dados primário e secundário, verifique se os dados podem ser gravados no banco de dados. Se sim, é um banco de dados primário. Se não, é um banco de dados secundário. Você pode usar a função pg_is_in_recovery() para determinar se um banco de dados é um banco de dados primário. Para mais detalhes, consulte Usar libpq para failover e separação de leitura/gravação.
Para implementar a separação de leitura/gravação, você precisa configurar duas fontes de dados. Para a primeira fonte de dados, defina targetServerType como primary para processar solicitações de gravação. Para a segunda fonte de dados:
- Se houver apenas uma réplica de leitura, defina targetServerType como preferSecondary para processar solicitações de leitura. Suponha que os endereços IP da instância primária e da réplica de leitura sejam 10.1.1.1 e 10.1.1.2, respectivamente.
jdbc:postgresql://10.1.1.2:5432,10.1.1.1:5432/${database}?targetServerType=preferSecondary
- Se houver duas réplicas de leitura, defina targetServerType como any para processar solicitações de leitura. Suponha que os endereços IP das réplicas de leitura sejam 10.1.1.2 e 10.1.1.3, respectivamente.
jdbc:postgresql://10.1.1.2:5432,10.1.1.3:5432/${database}?targetServerType=any&loadBalanceHosts=true