Configurando Replicação Síncrona para Alta Disponibilidade no PostgreSQL
Configurar o PostgreSQL para alta disponibilidade (HA) é crucial para qualquer aplicação de missão crítica. Embora a replicação assíncrona ofereça benefícios de desempenho, ela inerentemente carrega um risco de perda de dados se o servidor primário falhar antes que as alterações sejam totalmente transmitidas para o standby. A replicação de streaming síncrona resolve isso garantindo que uma transação só seja considerada confirmada após os dados terem sido gravados com sucesso no WAL (Write-Ahead Log) tanto do primário quanto de pelo menos um servidor standby designado. Isso garante um Objetivo de Ponto de Recuperação (RPO) de zero.
Este guia abrangente o orientará pelas etapas essenciais de configuração necessárias para estabelecer uma configuração de replicação robusta no PostgreSQL, com zero perda de dados. Focaremos em parâmetros críticos como wal_level e synchronous_commit, que sustentam essa arquitetura de alta disponibilidade.
Pré-requisitos
Antes de começar, certifique-se de ter dois servidores PostgreSQL configurados (Primário e Standby) executando versões principais idênticas do PostgreSQL. Ambos os servidores devem ter conectividade de rede. Para este guia, assumimos:
- Nome do Host/IP Primário:
pg_primary - Nome do Host/IP Standby:
pg_standby - Usuário de Replicação:
repl_user(criado com as permissões apropriadas) - Nome do Banco de Dados:
mydb
Etapa 1: Configurando o Servidor Primário
O servidor primário requer configurações específicas para habilitar a replicação de streaming e gerenciar o Write-Ahead Log (WAL) necessário para commits síncronos.
A. Ajustando postgresql.conf no Primário
Edite o arquivo postgresql.conf do servidor primário. Os seguintes parâmetros são obrigatórios para a replicação de streaming:
# --- Necessário para Replicação ---
listen_addresses = '*' # Permite conexões do standby
wal_level = replica # Deve ser 'replica' ou superior (ex: 'logical')
max_wal_senders = 10 # Conexões máximas simultâneas dos standbys
max_replication_slots = 10 # Slots necessários para fluxos de replicação persistentes
# --- Essencial para Commit Síncrono ---
synchronous_standby_names = '1 (standby_app_name)' # Especifica os standbys necessários
# --- Opcional, mas Recomendado ---
wal_log_hints = on # Recomendado para replicação mais segura, embora aumente o volume do WAL
shared_preload_libraries = 'pg_stat_statements' # Se estiver usando monitoramento
Explicação dos Parâmetros Chave:
wal_level = replica: Isso garante que informações suficientes sejam gravadas no WAL para permitir que um servidor standby reconstrua o estado do banco de dados. Para commits síncronos, este nível é o requisito mínimo.synchronous_standby_names: Esta é a configuração central para definir quais standbys devem reconhecer as escritas. Nós o definimos usando a sintaxe(N (nome_do_standby)). SeN=1, pelo menos um standby deve confirmar a escrita antes que a transação seja confirmada.
B. Configurando a Autenticação Baseada em Host (pg_hba.conf)
O servidor primário deve permitir que o usuário de replicação do(s) servidor(es) standby se conecte para fins de replicação.
Adicione uma entrada a pg_hba.conf no primário:
# TYPE DATABASE USER ADDRESS METHOD
host replication repl_user pg_standby/32 scram-sha-256
Substitua pg_standby/32 pelo endereço IP ou sub-rede real do seu servidor standby.
C. Criando o Slot de Replicação e o Usuário
Conecte-se ao PostgreSQL no servidor primário para criar o usuário necessário e o slot de replicação.
1. Criar Usuário de Replicação:
CREATE ROLE repl_user WITH REPLICATION LOGIN PASSWORD 'uma_senha_forte';
2. Criar Slot de Replicação:
Este slot garante que os segmentos WAL sejam retidos até que o standby confirme o recebimento, evitando perda de dados se o standby se desconectar temporariamente.
SELECT pg_create_physical_replication_slot('standby_app_name');
- Observação sobre Nomenclatura: O nome fornecido aqui (
standby_app_name) deve corresponder ao nome especificado emsynchronous_standby_namesno primário.
D. Reiniciando o Primário
Aplique todas as alterações de configuração reiniciando o serviço PostgreSQL no servidor primário.
sudo systemctl restart postgresql
Etapa 2: Configurando o Servidor Standby
O servidor standby é configurado para transmitir registros WAL do primário usando uma configuração de recuperação.
A. Backup Base
Antes de iniciar o streaming, o standby precisa de uma cópia completa do diretório de dados do primário. Pare o PostgreSQL no standby primeiro.
sudo systemctl stop postgresql
Faça o backup base usando pg_basebackup. Substitua os caminhos e detalhes de conexão conforme necessário:
# Exemplo usando a utilidade pg_basebackup
pg_basebackup -h pg_primary -D /var/lib/postgresql/15/main/ -U repl_user -P -Xs -R -W
-D: O diretório de dados de destino no standby.-U: O usuário de replicação.-P: Mostrar progresso.-Xs: Incluir arquivos WAL necessários durante o backup base.-R: Criar automaticamente o arquivostandby.signale gerar as configurações de conexão necessárias empostgresql.auto.conf(ou configuração de recuperação).
B. Configurando postgresql.conf no Standby
No standby, certifique-se de que postgresql.conf permita que ele atue como um réplica. A configuração chave aqui é definir o nome da aplicação, que deve corresponder ao nome do slot usado no primário.
# --- Necessário no Standby ---
primary_conninfo = 'host=pg_primary port=5432 user=repl_user password=a_strong_password application_name=standby_app_name'
hot_standby = on # Permite consultas de leitura durante o modo de recuperação/standby
C. Iniciando o Standby
Inicie o serviço PostgreSQL no servidor standby.
sudo systemctl start postgresql
Etapa 3: Verificação e Teste de Commit Síncrono
Uma vez que ambos os servidores estejam em execução, verifique a conexão e, em seguida, teste o comportamento síncrono.
A. Verificando o Status da Replicação
Conecte-se ao banco de dados primário e verifique a visualização pg_stat_replication:
SELECT client_addr, application_name, state, sync_state FROM pg_stat_replication;
Você deverá ver uma entrada para standby_app_name com sync_state como sync.
B. Testando Commit Síncrono
O parâmetro global que dita o quão arduamente o PostgreSQL espera é synchronous_commit. Para RPO=0, você deve usar um valor que force a sincronização.
1. Definindo o Comportamento Global
Se você configurou synchronous_standby_names no primário como mostrado na Etapa 1, o comportamento padrão forçará a espera pelos standbys necessários se synchronous_commit estiver definido como on (o padrão) ou remote_write.
Para a garantia mais forte, defina-o explicitamente em postgresql.conf como remote_write ou remote_apply (se você precisar que o standby tenha os dados gravados em disco, não apenas recebidos).
# Em postgresql.conf no Primário
synchronous_commit = remote_write
Aviso: Definir
synchronous_commit = remote_writeouonaumenta significativamente a latência da transação em comparação com os modos assíncronos (offoulocal). Essa latência está diretamente correlacionada com a velocidade da rede entre o primário e o standby síncrono.
2. Testando Dentro de uma Transação
Para testar transacionalmente (sem exigir uma alteração de configuração global), você pode defini-lo por sessão ou transação:
-- Conectar ao Primário
BEGIN;
SET LOCAL synchronous_commit = remote_write;
INSERT INTO sales (item, amount) VALUES ('Widget A', 100);
-- Este INSERT irá bloquear até que 'standby_app_name' confirme o recebimento.
COMMIT;
-- O COMMIT só é bem-sucedido após o standby reconhecer a escrita do WAL.
Se a conexão com o standby síncrono for perdida durante a transação, o primário esperará indefinidamente (se o standby se desconectar de forma limpa) ou fará fallback com base na configuração synchronous_commit_fallback_on_error (por padrão on, o que significa que a transação pode falhar ou travar se o primário não conseguir confirmar o status de sincronização).
Melhores Práticas para HA Síncrona
- Use Standbys Dedicados: Atribua apenas standbys que estejam fisicamente próximos (baixa latência) ao primário à sua lista de replicação síncrona. Alta latência impactará severamente o desempenho de escrita.
- Monitore o Lag de Replicação: Mesmo em modo síncrono, monitore o lag do standby. Um standby lento que ainda está tecnicamente 'sincronizado', mas leva muito tempo para processar o WAL, ainda pode impactar a experiência do usuário.
- Fallback de Conexão: Entenda a configuração
synchronous_commit_fallback_on_error. Se definida comooff, uma falha na comunicação com o standby síncrono durante um commit fará com que a transação no primário falhe, evitando potencial divergência de dados, mas impactando imediatamente a disponibilidade. - Use Múltiplos Standbys: Para redundância máxima dentro da configuração síncrona, configure
synchronous_standby_names = '2 (standby1, standby2)'para exigir commits de dois standbys distintos.