A replicação streaming do PostgreSQL fornece um mecanismo robusto para manter cópias em tempo real do seu banco de dados em múltiplos servidores. Seja para alta disponibilidade, recuperação de desastres ou escalabilidade de leitura, a replicação streaming oferece consistência em nível de bytes com lag mínimo. Este guia conduz você pela configuração de uma arquitetura primário-standby do zero, configuração de arquivamento WAL, monitoramento da saúde da replicação e planejamento de estratégias de failover.
Pré-requisitos
- Dois servidores Linux (Ubuntu 22.04+ ou RHEL 9+) com conectividade de rede
- PostgreSQL 16 ou posterior instalado em ambos os servidores
- Espaço em disco suficiente para arquivos WAL e backups base
- Acesso root ou sudo em ambas as máquinas
- Porta 5432 aberta entre os servidores primário e standby
- Familiaridade básica com os arquivos de configuração do PostgreSQL
Entendendo a Replicação no PostgreSQL
O PostgreSQL suporta dois modos principais de replicação: replicação streaming e replicação lógica. A replicação streaming opera no nível de bytes WAL (Write-Ahead Log), enviando um fluxo contínuo de registros WAL do primário para os standbys. Isso cria uma cópia binária exata de todo o cluster.
O processo de replicação segue este fluxo:
- O primário grava as mudanças em segmentos WAL
- O processo WAL sender transmite os registros para os standbys conectados
- O WAL receiver do standby grava os registros no WAL local
- O processo startup do standby reproduz os registros WAL para atualizar os arquivos de dados
A replicação streaming pode operar em modo assíncrono (padrão) ou síncrono. O modo assíncrono oferece melhor desempenho com lag mínimo, enquanto o síncrono garante zero perda de dados ao custo de latência na escrita.
Configuração do Servidor Primário
Edite o arquivo postgresql.conf do servidor primário para habilitar a replicação:
# /etc/postgresql/16/main/postgresql.conf
listen_addresses = '*'
wal_level = replica
max_wal_senders = 5
wal_keep_size = '1GB'
hot_standby = on
O parâmetro wal_level = replica garante que o WAL contenha informação suficiente para replicação. max_wal_senders controla quantas conexões de streaming simultâneas são permitidas. wal_keep_size impede que o primário recicle segmentos WAL antes que o standby os tenha consumido.
Em seguida, configure pg_hba.conf para permitir que o standby se conecte para replicação:
# /etc/postgresql/16/main/pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD
host replication replicator 10.0.1.20/32 scram-sha-256
Substitua 10.0.1.20 pelo endereço IP do seu servidor standby.
Crie um usuário dedicado para replicação:
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'your_secure_password';
Reinicie o PostgreSQL para aplicar as mudanças de configuração:
sudo systemctl restart postgresql
Configuração do Servidor Standby
No servidor standby, pare o PostgreSQL e limpe o diretório de dados existente:
sudo systemctl stop postgresql
sudo rm -rf /var/lib/postgresql/16/main/*
Execute pg_basebackup para clonar os dados do primário:
sudo -u postgres pg_basebackup \
-h 10.0.1.10 \
-U replicator \
-D /var/lib/postgresql/16/main \
-Fp -Xs -P -R
As flags têm propósitos específicos:
-Fp: Formato de saída plano-Xs: Transmite WAL durante o backup para evitar lacunas-P: Mostra o progresso-R: Cria automaticamentestandby.signale gravaprimary_conninfoempostgresql.auto.conf
Se preferir configuração manual, crie o sinal de standby e as configurações de conexão você mesmo:
touch /var/lib/postgresql/16/main/standby.signal
Adicione ao postgresql.conf no standby:
primary_conninfo = 'host=10.0.1.10 port=5432 user=replicator password=your_secure_password application_name=standby1'
hot_standby = on
Inicie o servidor standby:
sudo systemctl start postgresql
Arquivamento WAL
O arquivamento WAL fornece uma rede de segurança adicional ao copiar segmentos WAL completos para um local de arquivo. Isso permite recuperação point-in-time (PITR) e protege contra cenários onde o standby fica muito atrasado.
Configure o arquivamento no primário:
# /etc/postgresql/16/main/postgresql.conf
archive_mode = on
archive_command = 'cp %p /var/lib/postgresql/wal_archive/%f'
Crie o diretório de arquivo:
sudo mkdir -p /var/lib/postgresql/wal_archive
sudo chown postgres:postgres /var/lib/postgresql/wal_archive
Para ambientes de produção, use rsync ou uma solução de armazenamento em nuvem em vez de cp local:
archive_command = 'rsync -a %p backup-server:/wal_archive/%f'
Configure o standby para usar WAL arquivado como fallback com restore_command:
# No postgresql.conf do standby
restore_command = 'cp /mnt/wal_archive/%f %p'
Isso permite que o standby recupere segmentos WAL do arquivo quando o streaming fica atrasado.
Monitoramento do Lag de Replicação
Monitorar o lag de replicação é crítico para garantir que seu standby permaneça atualizado. No servidor primário, consulte pg_stat_replication:
SELECT
client_addr,
application_name,
state,
sent_lsn,
write_lsn,
flush_lsn,
replay_lsn,
pg_wal_lsn_diff(sent_lsn, replay_lsn) AS replay_lag_bytes,
write_lag,
flush_lag,
replay_lag
FROM pg_stat_replication;
No servidor standby, verifique o status do receptor e calcule o lag:
SELECT
status,
received_lsn,
latest_end_lsn,
last_msg_send_time,
last_msg_receipt_time
FROM pg_stat_wal_receiver;
-- Estimativa de lag baseada em tempo
SELECT
now() - pg_last_xact_replay_timestamp() AS replication_delay;
Configure um alerta quando o lag exceder seu limite:
#!/bin/bash
LAG_BYTES=$(psql -h primary -U monitor -t -c \
"SELECT pg_wal_lsn_diff(sent_lsn, replay_lsn) FROM pg_stat_replication WHERE application_name='standby1';")
if [ "$LAG_BYTES" -gt 104857600 ]; then
echo "ALERTA: Lag de replicação excede 100MB ($LAG_BYTES bytes)" | mail -s "PG Replication Alert" admin@example.com
fi
Estratégias de Failover
Quando o primário falha, você precisa de um plano claro de failover. O PostgreSQL fornece vários métodos de promoção:
Promoção manual:
# Usando pg_ctl
sudo -u postgres pg_ctl promote -D /var/lib/postgresql/16/main
# Usando SQL (PostgreSQL 12+)
SELECT pg_promote(wait := true, wait_seconds := 60);
Promoção por arquivo trigger:
Configure promote_trigger_file no postgresql.conf do standby:
promote_trigger_file = '/tmp/postgresql.trigger'
Crie o arquivo para acionar a promoção:
touch /tmp/postgresql.trigger
Failover automatizado com Patroni:
Para ambientes de produção, use uma ferramenta como Patroni com etcd:
# /etc/patroni/patroni.yml (trecho)
scope: pg-cluster
namespace: /db/
name: node1
restapi:
listen: 0.0.0.0:8008
etcd:
hosts: 10.0.1.100:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
maximum_lag_on_failover: 1048576
postgresql:
listen: 0.0.0.0:5432
data_dir: /var/lib/postgresql/16/main
authentication:
replication:
username: replicator
password: your_secure_password
Após o failover, o antigo primário deve ser reintroduzido como standby usando pg_rewind:
sudo -u postgres pg_rewind \
--target-pgdata=/var/lib/postgresql/16/main \
--source-server="host=10.0.1.20 port=5432 user=postgres"
Comparação: Streaming vs Replicação Lógica
| Característica | Replicação Streaming | Replicação Lógica |
|---|---|---|
| Nível de replicação | Nível de bytes (WAL) | Nível de linha (mudanças decodificadas) |
| Escopo do cluster | Cluster completo | Por tabela ou por banco de dados |
| Suporte entre versões | Requer mesma versão maior | Suporta versões maiores diferentes |
| Escrita no standby | Somente leitura (hot standby) | Leitura-escrita no subscriber |
| Replicação de DDL | Automática | Manual (não replicada) |
| Overhead de desempenho | Muito baixo | Moderado (custo de decodificação) |
| Complexidade de configuração | Simples | Moderada |
| Caso de uso | HA e recuperação de desastres | Replicação seletiva e migrações |
Escolha replicação streaming para alta disponibilidade do cluster completo. Escolha replicação lógica quando precisar de replicação seletiva de tabelas, atualizações entre versões ou subscribers com escrita.
Cenário Real
Você gerencia um banco de dados de produção de e-commerce que processa 5.000 transações por segundo. O negócio requer menos de 30 segundos de inatividade durante qualquer falha. Veja como arquitetar a solução:
O servidor primário (10.0.1.10) processa todas as escritas. O standby síncrono (10.0.1.20) no mesmo datacenter garante zero perda de dados. O standby assíncrono (10.0.2.10) em um datacenter remoto fornece recuperação de desastres.
Configure a replicação síncrona no primário:
synchronous_standby_names = 'FIRST 1 (standby_dc1, standby_dc2)'
synchronous_commit = on
Direcione as consultas de leitura para os standbys usando PgBouncer ou HAProxy:
# /etc/haproxy/haproxy.cfg (trecho)
listen pg-read
bind *:5433
mode tcp
balance roundrobin
option pgsql-check user haproxy
server standby1 10.0.1.20:5432 check
server standby2 10.0.2.10:5432 check
Essa arquitetura fornece zero perda de dados para falhas locais e perda mínima para eventos em nível de datacenter, enquanto descarrega o tráfego de leitura para os standbys.
Armadilhas e Casos Especiais
- Remoção de segmentos WAL: Se o standby desconectar por mais tempo do que
wal_keep_sizepermite, ele não consegue se atualizar via streaming. Sempre configure arquivamento WAL como rede de segurança ou use slots de replicação:SELECT pg_create_physical_replication_slot('standby1_slot'); - Slots de replicação e uso de disco: Slots de replicação não utilizados impedem a limpeza de WAL, potencialmente enchendo o disco. Monitore
pg_replication_slotse remova slots inativos - Transações grandes: Uma única transação massiva (importação em massa) gera enormes volumes de WAL que podem sobrecarregar o standby ou a rede. Divida operações grandes em lotes
- Latência de commit síncrono: Habilitar
synchronous_commit = oncom standbys síncronos adiciona o tempo de ida e volta da rede a cada commit. Teste o throughput de escrita antes de habilitar - Divergência de timeline: Após promover um standby, o antigo primário está em um timeline diferente. Você deve usar
pg_rewindou reconstruí-lo completamente antes de reintroduzi-lo como standby - Senha em primary_conninfo: Armazene credenciais em
.pgpassem vez de texto plano nos arquivos de configuração
Solução de Problemas
Standby não conecta:
# Verificar logs do standby
sudo tail -f /var/log/postgresql/postgresql-16-main.log
# Verificar conexões de replicação no primário
sudo -u postgres psql -c "SELECT * FROM pg_stat_replication;"
# Testar conectividade a partir do standby
psql -h 10.0.1.10 -U replicator -d postgres -c "IDENTIFY_SYSTEM;"
Lag de replicação crescendo:
-- Verificar se o standby está reproduzindo
SELECT pg_is_in_recovery(), pg_last_wal_replay_lsn();
-- Verificar consultas de longa duração bloqueando a reprodução
SELECT pid, query, state, wait_event FROM pg_stat_activity
WHERE state != 'idle' AND backend_type = 'client backend';
Arquivo WAL enchendo:
# Verificar status do arquivamento
sudo -u postgres psql -c "SELECT * FROM pg_stat_archiver;"
# Limpar arquivos antigos manualmente (manter pelo menos 1 dia)
find /var/lib/postgresql/wal_archive -mtime +1 -delete
Resumo
- A replicação streaming do PostgreSQL cria cópias binárias em tempo real de todo o seu cluster de banco de dados
- Configure
wal_level = replica,max_wal_senderse um usuário de replicação no primário - Use
pg_basebackupcom a flag-Rpara inicializar standbys com configuração automática - O arquivamento WAL fornece uma rede de segurança para standbys que ficam atrasados no streaming
- Monitore o lag de replicação via
pg_stat_replicationepg_stat_wal_receiver - Use Patroni ou ferramentas similares para failover automatizado em produção
- Slots de replicação impedem a remoção de WAL mas requerem monitoramento para evitar esgotamento de disco
- Sempre teste seu procedimento de failover antes de precisar dele em uma emergência