Este conteúdo foi traduzido por máquina para sua conveniência e a Huawei Cloud não pode garantir que o conteúdo foi traduzido com precisão. Para exibir o conteúdo original, use o link no canto superior direito para mudar para a página em inglês.
Central de ajuda/ Relational Database Service/ Melhores práticas/ RDS for PostgreSQL/ Uso de drivers de cliente para implementar failover e separação de leitura/gravação
Atualizado em 2024-09-24 GMT+08:00

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.
Tabela 1 Funções suportadas por libpq e JDBC

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

Tabela 2 Descrição do parâmetro

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.

  • any (padrão): libpq pode se conectar a qualquer banco de dados. Se a conexão for interrompida devido a uma falha no banco de dados, libpq tentará se conectar a outro banco de dados para implementar o failover.
  • read-write: libpq só pode se conectar a um banco de dados que suporte leitura e gravação. libpq tenta uma conexão com o primeiro banco de dados especificado. Se esse banco de dados suporta apenas operações de leitura ou gravação, libpq se desconecta dele e tenta se conectar ao segundo e assim por diante até que ele se conecte a um banco de dados que suporta leitura e gravação.
  • read-only: libpq só pode se conectar a um banco de dados somente leitura. libpq tenta uma conexão com o primeiro banco de dados especificado. Se esse banco de dados não for um banco de dados somente leitura, libpq se desconecta dele e tenta se conectar ao segundo banco de dados e assim por diante até se conectar a um banco de dados somente leitura. Esse valor não é suportado no RDS for PostgreSQL 13 (libpq.so.5.13) ou em versões anteriores.

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.

Tabela 3 Descrição do parâmetro

Parâmetro

Descrição

Exemplo de valor

targetServerType

Tipo do banco de dados a ser conectado.

  • any: qualquer banco de dados.
  • primary: banco de dados primário (gravável e legível). Para versões anteriores ao JDBC 42.2.0, use o valor do parâmetro master.
  • secondary: banco de dados secundário (legível). Para versões anteriores ao JDBC 42.2.0, use o valor do parâmetro slave.
  • preferSecondary: o banco de dados secundário é preferido. Se nenhum banco de dados secundário estiver disponível, o banco de dados primário será conectado. Para versões anteriores ao JDBC 42.2.0, use o valor do parâmetro preferSlave.

loadBalanceHosts

Sequência de bancos de dados a serem conectados.

  • False (padrão): os bancos de dados são conectados na sequência definida no URL.
  • True: os bancos de dados são conectados aleatoriamente.

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