Replicação
Cópias do banco para leitura e para tolerar falhas, e o atraso entre a principal e as réplicas.
As decisões de replicação são cinco: síncrona ou assíncrona, quantas réplicas e onde, como trocar de principal, como rotear as leituras e o que monitorar.
Síncrona ou assíncrona
| Assíncrona | Síncrona com uma réplica | Síncrona com quórum (ANY 1 de 2 ou mais) | |
|---|---|---|---|
Custo por COMMIT | Nenhum | Uma ida e volta até a réplica (6,5 contra 18,3 ms no teste) | Uma ida e volta até a réplica mais rápida |
| Perda numa troca de principal | O que não foi enviado (no teste, 1.000 gravações confirmadas) | Nenhuma | Nenhuma |
| Se uma réplica cair | Nada muda | As gravações travam | Nada muda, se outra responder |
| Bom para | A maioria dos sistemas | Raramente: o risco de travar é alto | Dados que não podem se perder: pagamentos, saldos |
A replicação síncrona com uma única réplica é a pior combinação: junta o custo do síncrono com a fragilidade de depender de uma máquina. No teste, uma réplica síncrona fora do ar deixou um INSERT parado por tempo indeterminado, sem respeitar o statement_timeout.
O synchronous_commit pode ser ajustado por transação. Um sistema assíncrono pode exigir confirmação síncrona só nas gravações críticas (SET LOCAL synchronous_commit = remote_write), e o contrário também vale.
Quantas réplicas e onde
| Topologia | Protege contra | Custo |
|---|---|---|
| Uma réplica na mesma zona | Falha do servidor | Baixo |
| Réplica em outra zona da mesma região | Falha de uma zona da nuvem | Pouca latência a mais |
| Réplica em outra região | Desastre regional | Latência alta: síncrona fica cara demais; assíncrona perde mais numa troca |
| Réplicas em cascata (réplica de réplica) | Carga de envio no principal | Mais atraso nas réplicas da ponta |
Réplica com atraso proposital (recovery_min_apply_delay) | Um DELETE errado: a réplica ainda tem os dados por algumas horas | Não serve para leitura nem para troca rápida |
Uma combinação comum: uma réplica síncrona em quórum na mesma região para não perder dados, e uma assíncrona em outra região para desastres.
Como trocar de principal
| Forma | Como funciona | Cuidados |
|---|---|---|
| Manual | Alguém promove a réplica (pg_promote()) e aponta a aplicação para ela | Lento, e às três da manhã |
| Automática, com um gerenciador (Patroni, repmgr, pg_auto_failover) | O gerenciador detecta a falha, escolhe a réplica e a promove | Precisa de um consenso externo (etcd, Consul) para não promover duas |
| Banco gerenciado (RDS, Cloud SQL, Azure) | O serviço faz a troca e mantém o mesmo endereço | Confira o tempo de troca e o que se perde no modo escolhido |
O risco principal de uma troca é o cérebro dividido (split brain): o principal antigo volta e continua aceitando gravações, e agora há dois. Os gerenciadores impedem isso com um líder eleito por consenso e isolando o antigo antes de promover o novo.
E a aplicação precisa achar o principal novo: um endereço que acompanha a troca (DNS, proxy, ou uma lista de servidores na string de conexão com target_session_attrs=read-write), e reconexão automática no pool.
Como rotear as leituras
| Forma | Como funciona | Quando usar |
|---|---|---|
| Tudo no principal | Réplicas só para tolerar falhas | O padrão, até o principal ficar sobrecarregado |
| Leituras separadas por tipo | Relatórios, buscas e listagens na réplica; o resto no principal | A maioria dos sistemas com réplicas de leitura |
| Ler o que gravou | Depois de gravar, a leitura vai para o principal, ou para uma réplica que já aplicou o LSN da gravação | Telas que mostram o que o usuário acabou de alterar |
| Afinidade por tempo | Por alguns segundos depois de gravar, o usuário lê do principal | Simples, sem LSN; o tempo é um chute |
Síncrono com remote_apply | A réplica já aplicou quando o COMMIT volta | Quando toda leitura na réplica precisa ver as gravações confirmadas |
O "ler o que gravou" com LSN é o mais preciso: a aplicação guarda o LSN da última gravação do usuário (na sessão, num cookie) e só lê de uma réplica que já passou dele. A Implementação mostra isso nas cinco linguagens, e um erro que o teste encontrou: o LSN precisa ser lido depois da confirmação.
Decisões que dependem do valor exato (saldo, estoque, permissões) leem do principal, sempre.
O que monitorar
| Métrica | Onde | Por quê |
|---|---|---|
| Atraso de replicação, em bytes e em tempo | pg_stat_replication no principal, pg_last_xact_replay_timestamp() na réplica | Quanto as leituras estão atrasadas, e quanto se perde numa troca |
| Slots e WAL retido | pg_replication_slots | No teste, um slot abandonado reteve 2,5 GB |
| Estado das réplicas síncronas | sync_state em pg_stat_replication | Uma síncrona fora trava as gravações |
| Sessões esperando a réplica | wait_event = 'SyncRep' em pg_stat_activity | O sinal de que as gravações estão paradas |
E configure max_slot_wal_keep_size: ele troca a queda do principal por disco cheio pela perda de uma réplica, que é recuperável.
Resumo da decisão
- Assíncrona para a maioria; síncrona com quórum para dados que não podem se perder, nunca com uma única réplica.
- Réplicas em outra zona, e uma em outra região para desastres.
- Troca automática com consenso, ou um banco gerenciado, e a aplicação reconectando no principal novo.
- Leituras na réplica só onde o atraso é aceitável, com "ler o que gravou" por LSN nas telas que precisam.
- Monitorar atraso, slots e esperas, com
max_slot_wal_keep_sizeconfigurado.
O próximo nível mostra o roteamento com LSN nas cinco linguagens e a configuração testada.
Prompts para aprofundar
Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.
Planejar a replicação do meu banco
Quero planejar a replicação do banco do meu sistema. Pergunte qual banco e onde ele roda, quanto de dado eu aceito perder numa falha, quanto tempo o sistema pode ficar fora, o volume de leituras e gravações e se o banco é gerenciado. Proponha: 1. O modo de replicação e quantas réplicas, e onde. 2. Como a troca de principal acontece. 3. Quais leituras vão para as réplicas. 4. O que monitorar e os alertas. 5. Como testar uma troca de principal antes de precisar dela.
Separar leituras e gravações na aplicação
Quero que a minha aplicação mande as leituras para as réplicas. Pergunte qual linguagem, framework e ORM eu uso, e quais telas e rotas existem. Me ajude a: 1. Configurar as conexões com o principal e as réplicas. 2. Classificar as leituras: quais aceitam atraso e quais não. 3. Implementar "ler o que gravou" para as telas que precisam. 4. Lidar com uma réplica fora do ar ou muito atrasada. 5. Testar com a réplica pausada.
Ensaiar uma troca de principal
Quero ensaiar uma troca de principal antes que ela aconteça de verdade. Pergunte qual banco, como a replicação está configurada e como a aplicação se conecta. Monte comigo o roteiro do ensaio: o que medir antes, como provocar a falha, o que observar na aplicação, como confirmar que nada se perdeu (ou quanto se perdeu) e como voltar ao estado normal. No final, liste o que precisa mudar se o ensaio mostrar problemas.