Compreendendo e Executando Cenários de Failover vs. Switchover no PostgreSQL

Aprenda quando usar switchover ou failover no PostgreSQL, como verificar a segurança da réplica e como evitar split-brain durante eventos de alta disponibilidade.

Compreendendo e Executando Cenários de Failover vs. Switchover no PostgreSQL

A diferença entre failover e switchover no PostgreSQL não é acadêmica quando você é a pessoa segurando o pager. Um switchover é planejado: você ainda tem um primário saudável, pode drenar as escritas e pode escolher o melhor momento para mover a função gravável para um standby. Um failover é o que você faz quando o primário se foi, está inacessível ou inseguro para continuar servindo tráfego.

Essa única diferença muda tudo. Durante um switchover, sua principal tarefa é paciência: comprovar que o standby alcançou antes da promoção. Durante um failover, sua principal tarefa é contenção: garantir que o antigo primário não possa continuar aceitando escritas após a promoção de um standby. A maioria dos incidentes feios de HA no PostgreSQL vem de apressar uma dessas duas tarefas.

Fundamentos de Replicação: A Base do HA

A Alta Disponibilidade do PostgreSQL é construída sobre replicação de streaming, onde um servidor atua como Primário (ou Mestre) e um ou mais servidores atuam como Standbys (ou Réplicas). O Primário transmite registros de write-ahead log (WAL) para os Standbys para mantê-los sincronizados.

Para gerenciar essas funções de forma eficaz, configurações específicas são necessárias tanto no nó primário quanto nos nós réplica:

Configurações Críticas

Essas configurações governam como a replicação opera e como os nós se identificam:

  • wal_level: Deve ser definido como replica ou superior (idealmente logical se usar ferramentas que exigem decodificação lógica) no Primário.
  • max_wal_senders: Define o número máximo de conexões simultâneas de remetentes WAL. Dimensione para todos os standbys físicos, backups de base e ferramentas de replicação que possam conectar ao mesmo tempo.
  • hot_standby: Deve ser definido como on no postgresql.conf do servidor standby para permitir consultas somente leitura durante a replicação.
  • synchronous_commit: Controla quando uma transação é confirmada. Só fornece durabilidade mais forte com replicação síncrona configurada corretamente; por si só, não torna um standby atual.
  • primary_conninfo: Definido no standby, detalhando informações de conexão (host, porta, usuário, senha) para conectar ao Primário atual.

Melhor Prática: Coloque um endpoint estável na frente do PostgreSQL, como HAProxy, PgBouncer atrás de um IP virtual, um registro de descoberta de serviço ou a abstração de serviço da sua plataforma. As aplicações não devem precisar saber qual nó é o primário hoje.

Switchover: A Transição Planejada

Um Switchover é um processo controlado e gracioso onde o nó Primário ativo é intencionalmente descomissionado, e um Standby designado é promovido para tomar seu lugar. Este procedimento é tipicamente usado para manutenção planejada, upgrades de versão ou substituições de hardware.

Passos para um Switchover Controlado

O objetivo de um switchover é garantir perda zero de dados aguardando que todas as transações em andamento sejam replicadas antes da promoção.

  1. Parar Escritas no Primário Atual: O primeiro passo é impedir que novas transações sejam confirmadas no Primário atual. Isso é frequentemente alcançado definindo default_transaction_read_only = on ou desligando temporariamente as conexões dos clientes.
  2. Aguardar a Recuperação da Replicação: Garantir que o Standby designado recebeu e aplicou todos os registros WAL restantes do Primário. Você pode verificar o lag de replicação usando pg_stat_replication no Primário ou examinando o status de recuperação do standby.
  3. Iniciar a Promoção do Standby: Execute o comando para promover o servidor Standby escolhido para a função de Primário. O comando específico depende da ferramenta de gerenciamento usada (por exemplo, pg_ctl promote ou um comando do gerenciador de cluster).
  4. Reconfigurar o Antigo Primário: Uma vez que o Standby é promovido com sucesso, o antigo Primário deve ser reconfigurado para seguir o novo Primário como um Standby. Isso envolve atualizar seu primary_conninfo.
  5. Redirecionar Aplicações: Atualize o balanceador de carga ou pooler de conexão para direcionar o tráfego para o novo servidor Primário.

Uma lista de verificação prática de switchover geralmente parece mais comum do que dramática. Anuncie uma breve pausa de escrita, pare os workers em segundo plano que continuam escrevendo, coloque a aplicação em modo de manutenção ou drene o pool de escritores, e então verifique a posição de replicação. No antigo primário, pg_stat_replication mostra se o standby recebeu e liberou o WAL. No standby, pg_last_wal_receive_lsn() e pg_last_wal_replay_lsn() ajudam a ver se o WAL meramente chegou ou foi realmente reproduzido.

Não promova um standby só porque ele está conectado. Um standby pode estar conectado e ainda assim estar segundos ou minutos atrasado se estiver reproduzindo uma transação grande, esperando por I/O de disco, ou se recuperando após uma pausa de rede. Para um switchover planejado, você quer que a reprodução esteja atualizada antes da promoção. Se sessões somente leitura estão rodando no standby, verifique também se consultas de longa duração estão atrasando a reprodução do WAL.

Após a promoção, teste a função diretamente:

SELECT pg_is_in_recovery();

O nó promovido deve retornar false. O nó rebaixado, após ser reconstruído ou reconfigurado como standby, deve retornar true.

O lado da aplicação merece o mesmo cuidado. Antes do switchover, saiba como os clientes descobrem o escritor. Se eles se conectam a um nome DNS, entenda o TTL do DNS e se os clientes armazenam endereços em cache por mais tempo que o esperado. Se eles se conectam através do PgBouncer, decida se você precisa pausar o pool, recarregá-lo ou reiniciá-lo. Se você usa HAProxy, certifique-se de que a verificação de saúde testa o status gravável, não apenas se a porta 5432 está aberta. Um standby com PostgreSQL rodando não é um alvo de escrita válido.

Eu também gosto de anotar o ponto de reversão. Antes da promoção, você geralmente pode parar, reabrir escritas no antigo primário e tentar novamente mais tarde. Após a promoção, a reversão se torna uma nova mudança de função, não um simples desfazer. Isso não significa que a promoção é perigosa; significa que o operador deve saber de que lado da linha eles estão.

Failover: A Resposta de Emergência

Failover é um procedimento imediato e reativo acionado quando o servidor Primário atual falha inesperadamente (por exemplo, falha de hardware, partição de rede, erro de software) e não pode ser trazido de volta online rapidamente.

Failover inerentemente carrega um risco maior de perda de dados porque não há garantia de que as últimas transações confirmadas tiveram tempo de fluir para os Standbys antes da falha ocorrer.

Executando um Failover de Emergência

Procedimentos de failover são projetados para velocidade e recuperação, frequentemente utilizando ferramentas especializadas para automatizar a promoção.

  1. Determinar a Saúde do Antigo Primário: Verifique se o Primário original está realmente indisponível e não apenas experimentando um problema de rede transitório (isso previne cenários perigosos de 'split-brain').
  2. Selecionar o Melhor Standby: Escolha o Standby com o menor lag de replicação (aquele que está mais à frente no fluxo WAL).
  3. Promover o Standby: Imediatamente promova o Standby selecionado usando o comando de promoção (pg_ctl promote).
  4. Lidar com a Perda de Dados (Se Necessário): Se o cluster utiliza replicação assíncrona, os dados perdidos no Primário com falha podem precisar ser reconciliados manualmente ou simplesmente aceitos, dependendo da tolerância da aplicação.
  5. Reconfigurar o Antigo Primário: Uma vez que o Primário original é recuperado, ele deve ser limpo, reinicializado (frequentemente exigindo um backup de base do novo Primário) e configurado para seguir o novo Primário.

A parte difícil do failover não é digitar pg_ctl promote. A parte difícil é decidir que o antigo primário deve ser tratado como inseguro até prova em contrário. Se o antigo primário ainda está rodando mas isolado da aplicação ou do standby, você pode ter split-brain: dois servidores PostgreSQL graváveis aceitando históricos diferentes. Uma vez que isso acontece, o PostgreSQL não vai mesclar os históricos para você. Você está olhando para reconciliação manual de dados ou restaurar um lado a partir do backup.

Em um incidente real, eu prefiro gastar um minuto extra isolando o antigo primário do que passar o dia seguinte explicando por que dois registros de pedido discordam. Isolamento pode significar desligar a VM antiga, desanexar sua interface de rede, desabilitar o endpoint do escritor, ou usar um mecanismo de nuvem/provedor que garanta que o host antigo não possa receber escritas. O método exato depende da sua infraestrutura, mas o requisito é simples: antes que os clientes escrevam no novo primário, o antigo primário não deve ser gravável por esses clientes.

Após o failover, espere limpeza. Se o antigo primário voltar, não o aponte casualmente para o novo primário e espere que ele alcance. Ele pode conter WAL que pertence à linha do tempo antiga. Em muitos ambientes, o caminho mais seguro é pg_rewind se os pré-requisitos forem atendidos, ou um backup de base fresco do novo primário se não forem.

Um detalhe que é esquecido durante o trabalho de emergência é a história dos slots de replicação. Se o antigo primário usava slots de replicação física para standbys, esses slots não se movem magicamente com o standby promovido a menos que sua ferramenta de HA os gerencie. Após o failover, verifique se o novo primário tem os slots que seus standbys sobreviventes precisam, e verifique se algum slot abandonado está retendo WAL para sempre. Um slot esquecido pode encher um disco horas após a interrupção visível terminar.

Use a mesma disciplina para backups. Uma vez que o cluster tem um novo primário, confirme que os backups e o arquivamento WAL agora seguem esse primário. Um failover que restaura o serviço mas silenciosamente para os backups é apenas metade de uma recuperação.

Ferramentas para Promoção Segura: Repmgr vs. Patroni

Embora a promoção manual usando pg_ctl seja possível, ambientes HA robustos dependem de ferramentas dedicadas para gerenciar a coreografia complexa necessária para failover e switchover, lidando automaticamente com mudanças de configuração e gerenciamento de estado do cluster.

Repmgr (Gerenciador de Replicação)

repmgr é uma ferramenta leve que ajuda a registrar nós, monitorar replicação e realizar mudanças de função controladas. Os comandos exatos dependem da versão e do layout do cluster, mas o padrão comum é:

  • Switchover: Execute um repmgr standby switchover planejado a partir do standby que deve se tornar primário, após confirmar a saúde da replicação.
  • Failover: Deixe repmgrd realizar failover automático apenas se o comportamento de isolamento e quorum/testemunha for compreendido e testado.

Patroni

Patroni utiliza Stores de Consenso Distribuído (como etcd, ZooKeeper ou Consul) para gerenciar o estado do cluster, elegendo automaticamente um novo Primário mediante detecção de falha. Patroni automatiza amplamente tanto switchovers quanto failovers através de chamadas de API ou operadores Kubernetes, reduzindo drasticamente a intervenção manual.

Exemplo usando Patroni (Comando Conceitual de Promoção):

# Acionando um switchover via API REST do Patroni
curl -X POST http://patroni-api-endpoint/switchover -H "Content-Type: application/json" -d '{"target": "standby_node_name"}'

Aviso sobre Split-Brain: O maior perigo durante failover automatizado é o cenário de 'split-brain', onde dois nós acreditam erroneamente que são o Primário devido a particionamento de rede. Ferramentas como Patroni mitigam isso usando mecanismos de quorum, enquanto configurações manuais exigem mecanismos estritos de isolamento (como controles de energia) para garantir que apenas um Primário exista.

Resumo das Diferenças

Característica Switchover (Planejado) Failover (Emergência)
Gatilho Manutenção, upgrade, escolha administrativa Falha do Primário (crash, interrupção)
Risco de Perda de Dados Quase Zero (se cronometrado corretamente) Médio a Alto (depende do modo de replicação)
Expectativa de Downtime Downtime curto e controlado Downtime imediato e reativo
Preparação Requer coordenação prévia e confirmação de sincronia WAL Requer ação imediata e confiança na saúde do Standby

Um Pequeno Runbook Que Você Pode Adaptar

Para um switchover planejado, um runbook compacto pode ser assim:

  1. Confirme que o standby escolhido está saudável e reproduzindo WAL.
  2. Pause as escritas da aplicação e jobs em segundo plano.
  3. Confirme que a reprodução da replicação alcançou.
  4. Promova o standby através da ferramenta de HA.
  5. Mova o endpoint do escritor.
  6. Confirme que pg_is_in_recovery() é false no novo primário.
  7. Reconstrua ou reverta o antigo primário como standby.
  8. Retome as escritas e monitore erros, replicação e contagens de conexão.

Para failover, a ordem muda:

  1. Confirme que o primário falhou ou está inseguro.
  2. Isole o antigo primário.
  3. Escolha o standby mais avançado.
  4. Promova-o através da ferramenta de HA.
  5. Mova o endpoint do escritor uma vez.
  6. Confirme que as escritas funcionam no novo primário.
  7. Verifique réplicas, slots, backups e arquivamento WAL.
  8. Reintroduza o antigo primário apenas através de rewind ou reconstrução.

Os comandos variam por ferramenta, mas as propriedades de segurança não. Um primário gravável, estado de replicação conhecido, roteamento de cliente testado e uma maneira limpa de trazer nós com falha de volta.

Antes de confiar em qualquer design de HA, ensaie ambos os caminhos em um ambiente não produtivo. Um exercício de switchover deve provar que as aplicações reconectam limpo, o antigo primário pode se tornar um standby novamente, e o monitoramento segue a nova função. Um exercício de failover deve provar algo mais estrito: o primário com falha está isolado, o standby escolhido para promoção é o melhor candidato disponível, o endpoint do escritor da aplicação se move uma vez, e o antigo primário não pode se juntar novamente sem rewind ou reconstrução.

As equipes de HA mais seguras do PostgreSQL tratam failover como um fluxo de trabalho operacional testado, não um comando heroico digitado durante uma interrupção.