Configurando Replicação Síncrona para Alta Disponibilidade no PostgreSQL

Aprenda a configurar alta disponibilidade do PostgreSQL com perda zero de dados (RPO=0) usando replicação por streaming síncrona. Este tutorial passo a passo abrange configurações essenciais para `wal_level`, slots de replicação, `pg_basebackup` e a configuração correta dos parâmetros `synchronous_commit` nos servidores primário e em standby para garantir a durabilidade das transações em ambientes críticos.

39 visualizações

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)). Se N=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 em synchronous_standby_names no 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 arquivo standby.signal e gerar as configurações de conexão necessárias em postgresql.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_write ou on aumenta significativamente a latência da transação em comparação com os modos assíncronos (off ou local). 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 como off, 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.