1 pontos por GN⁺ 2025-11-16 | 1 comentários | Compartilhar no WhatsApp
  • Caso em que um bug de condição de corrida ocorrido no AWS Aurora RDS foi confirmado experimentalmente, com a AWS validando a causa
  • A Hightouch, durante a expansão do sistema de processamento de eventos, descobriu que no processo de failover do Aurora ocorria uma falha na troca da instância de escrita
  • A análise dos logs confirmou que duas instâncias executaram operações de escrita ao mesmo tempo, causando conflito na camada de armazenamento e encerramento de processos
  • A AWS confirmou oficialmente que a causa foi a promoção de um novo writer antes da conclusão do rebaixamento do writer anterior, devido a um problema no processamento de sinais internos
  • Este caso destaca a importância do controle de concorrência em sistemas distribuídos de grande escala e a necessidade de interromper escritas durante o failover

Contexto

  • Em 20 de outubro de 2025, ocorreu uma falha na região us-east-1 da AWS causada por um bug de condição de corrida no sistema de gerenciamento de DNS
  • Por causa disso, a Hightouch viu o backlog de processamento de eventos disparar, chegando ao limite do sistema
  • Para garantir capacidade de processamento, em 23 de outubro foi feito um upgrade das instâncias Aurora RDS e, nesse processo, foi descoberto um novo bug de condição de corrida

Estrutura do sistema de eventos da Hightouch

  • O sistema responsável pela coleta e entrega de eventos é composto por Kubernetes, Kafka e Postgres (Aurora)
  • O Postgres é usado como fila de metadados em lote e processa 500 mil eventos por segundo em menos de 1 segundo
  • O Aurora PostgreSQL é composto por uma instância somente de escrita (primary), instâncias somente de leitura (replica) e uma camada de armazenamento compartilhada

Plano de upgrade

  • Adicionar uma instância de leitura → fazer upgrade do reader existente e atribuir prioridade de failover → executar o failover → fazer upgrade do writer existente → remover o reader temporário
  • Esse procedimento é o método descrito na documentação da AWS e já havia sido validado por testes de carga em ambiente de staging

Tentativa de upgrade e surgimento do problema

  • Em 23 de outubro, às 16:39 EDT, após a execução do failover, ocorreu o fenômeno em que o writer anterior retornou novamente como primary
  • Nas duas tentativas, o resultado foi o mesmo, e alguns serviços passaram a apresentar erro de impossibilidade de escrita (DatabaseError: cannot execute UPDATE in a read-only transaction)
  • A análise dos logs confirmou registros de que duas instâncias executaram operações de escrita simultaneamente e foram encerradas por conflito de armazenamento

Causa da condição de corrida

  • Durante o processo de failover do Aurora, surgiu uma condição de corrida entre a etapa 3 (rebaixamento do writer anterior) e a etapa 4 (promoção do novo writer)
  • Com isso, as duas instâncias passaram a ter permissão de escrita ao mesmo tempo, gerando conflito
  • Quando a nova tentativa foi feita com o tráfego de escrita removido, o failover foi concluído normalmente, comprovando a hipótese da condição de corrida

Confirmação e resposta da AWS

  • Após revisão interna, a AWS confirmou que a causa era um erro no processamento do sinal de rebaixamento do writer, sem relação com a configuração da Hightouch nem com o padrão de tráfego
  • A correção está incluída no roadmap, e a recomendação temporária é interromper as escritas durante o failover

Medidas finais

  • A Hightouch concluiu o upgrade do cluster e
    • adicionou um procedimento de interrupção de escrita antes de failovers intencionais
    • reforçou o monitoramento da mudança de papel do writer
    • atualizou o manual operacional (playbook)

Principais lições

  1. É necessário preparar recuperação para transições de estado inesperadas durante migrações
  2. Garantir observabilidade é essencial para detectar problemas
  3. É importante projetar para minimizar o impacto entre componentes de sistemas distribuídos
  4. É preciso reconhecer a diferença entre ambiente de teste e ambiente de produção

Não há informações adicionais no texto original

1 comentários

 
GN⁺ 2025-11-16
Comentários no Hacker News
  • Ao ler este texto, parece que durante um failover manual a aplicação sempre falha se tentar manter o tráfego de escrita normalmente
    Mas isso levanta algumas dúvidas. Fico me perguntando por que outros usuários do Aurora não enfrentam esse problema o tempo todo, como a AWS não saberia disso e, se souber, por que não trataria isso como um incidente crítico de nível P0
    Talvez haja alguma condição sutil, como o estado de transações em andamento ou timeouts, influenciando o comportamento

    • Pela minha experiência lidando com um problema parecido no Azure, muita gente passa por isso, mas como reiniciar resolve, simplesmente deixam pra lá. Encontrar a causa raiz é difícil, e o processo de analisar isso com o fornecedor é tão doloroso que a maioria desiste
    • Nós também confirmamos o mesmo problema trabalhando junto com a AWS. O padrão de tráfego não tinha nada de especial, e em outras regiões não foi reproduzido. Há uma boa chance de isso ser uma falha fundamental no mecanismo de failover do Aurora
    • No passado, com Python + MySQL, já tive um bug em que SELECT ... FOR UPDATE falhava silenciosamente e a transação mudava para o modo autocommit. Ninguém ligou e eu fiquei falando disso sozinho, mas alguns meses depois outra pessoa entrou em contato dizendo que tinha passado pelo mesmo problema. No fim isso foi corrigido, mas eu já tinha perdido o interesse
      Link relacionado: pergunta no Stack Overflow
    • A AWS quase não divulga informações internas. Como não fornece detalhes além do nível de API, dá a sensação de que casos assim são tratados como situações raras e deixados de lado
    • Parte do problema também pode estar em como a aplicação reage a um failover revertido. Parece que o cache se corrompeu e continuou tentando gravar no primário errado. Mesmo que esse tipo de falha aconteça às vezes, como uma nova tentativa costuma funcionar, pode ser que os usuários não reportem isso à AWS e a AWS nem fique sabendo
  • Já vi comportamentos inesperados várias vezes no Aurora PostgreSQL
    Em especial, durante o Zero Downtime Patching (ZDP), o estado da sessão era mantido de forma incorreta, fazendo até consultas simples serem canceladas muito antes do statement_timeout
    Meu palpite é que, quando o cliente se reconecta, o Aurora herda o estado antigo de temporizadores da sessão anterior, e por isso a consulta é cancelada imediatamente

  • Nós também fazemos failover regularmente em um ambiente com tráfego de escrita muito alto, mas operamos isso de forma estável com um processo automatizado usando o AWS JDBC wrapper

    • Na prática, a camada de armazenamento do Aurora evitou violações de ACID, ou seja, a integridade dos dados foi preservada
  • É surpreendente ver um problema desses quando se paga justamente acreditando que o Aurora vai manter esse tipo de invariância básica

    • Ainda assim, a própria camada de armazenamento bloqueou escritas simultâneas e funcionou corretamente
  • Pelos logs e pela explicação da AWS, parece que a hipótese do autor original está errada
    Parece que, depois da falha na promoção, um processo externo de monitoramento detectou a inconsistência no estado do cluster e encerrou o processo à força com kill -9. As mensagens relacionadas ao subsistema de armazenamento vieram depois disso

  • Gostaria de perguntar sobre a comparação de desempenho entre Aurora e RDS Postgres
    Se não houver necessidade de Multi-AZ ou failover rápido, seria possível obter desempenho melhor no RDS com uma configuração gp3 64k IOPS? O Aurora parece ter desempenho fraco de insert e custo alto. Também é difícil confiar nos benchmarks, porque muitos nem deixam clara a configuração usada no RDS

    • No Aurora PG 14, nós obtivemos melhor desempenho e custo menor com uma configuração de 1 writer + 1~2 readers. O Aurora leva vantagem porque a cobrança de armazenamento é por cluster, não por instância.
      Além disso, não é preciso provisionar IOPS manualmente, e ele oferece cerca de 80k IOPS.
      Também há dois modelos de cobrança de IO: o pay-per-IO é melhor para cargas leves, enquanto o modo de tarifa fixa é vantajoso para workloads com muito IO.
      E, só para constar, o Serverless quase sempre foi antieconômico. Só vale a pena quando há picos curtos de uso
    • Nossa equipe sofreu uma explosão nos custos de I/O no Aurora Postgres RDS. Apenas algumas fuzzy queries geraram mais de US$ 3.000 por mês, quando o esperado era ficar abaixo de US$ 100
    • Ficamos decepcionados com o custo, desempenho e latência do Aurora e acabamos migrando para PostgreSQL on-premises
    • No caso do Aurora MySQL, para igualar o mesmo IOPS no RDS, o custo ficava muito mais alto
    • O Aurora não usa EBS, e não é possível escolher o tipo de armazenamento nem a latência. Só dá para escolher o modelo de cobrança de IO
  • Isso mostra bem o “modelo de blocos de Lego” de que os engenheiros da AWS falam
    A camada de armazenamento foi projetada de forma totalmente independente, então mesmo quando o serviço de cima falhou, a consistência dos dados foi preservada. Acho que é um bom exemplo da engenharia da AWS

  • Foi dito que a AWS recomendou “parar as escritas durante o failover”, e fiquei curioso se seria possível compartilhar o número do caso relacionado

    • Nós também usamos Aurora MySQL, então queria confirmar se essa recomendação também se aplica ao MySQL
  • Fico aliviado em saber que não fui o único a passar por esse problema

    • No começo, o AWS Support rebateu dizendo que era por causa de replication lag, mas eles chegaram a essa conclusão olhando métricas antigas de 24 horas antes. Eu realmente queria entender que tipo de falha ocorreu e por que não foi reproduzida em outras regiões
  • A arquitetura do Aurora de separação entre computação e armazenamento é interessante
    O Hyperscale do MSSQL tem uma estrutura parecida, e é praticamente o único produto da Azure que eu realmente consideraria usar