Fundamentos da computação em nuvem
Alta disponibilidade e tolerância a falhas
Por que um sistema que se recupera de uma falha em menos de 2 minutos e um sistema que nunca pisca resolvem o mesmo problema com orçamentos diferentes, e os padrões de redundância que times de nuvem usam para construir cada um.
- Definir alta disponibilidade e tolerância a falhas e explicar o que as separa
- Explicar como distribuir capacidade de computação e banco de dados entre zonas de disponibilidade elimina um ponto único de falha
- Comparar redundância ativo-ativo e ativo-passivo usando um exemplo de failover
- Aplicar a distinção entre alta disponibilidade e tolerância a falhas a um cenário e identificar qual padrão o requisito realmente pede
A falha de hardware às 2h da manhã
Uma rede de varejo roda a API de checkout em uma única instância virtual. Às 2h da manhã, o host físico por trás dela falha, silenciosa e completamente, do jeito que hardware sempre acaba falhando, não importa de quem é o logotipo no rack. A instância some, e o checkout some junto, até alguém perceber e subir uma instância nova. Aquela instância isolada era um ponto único de falha: 1 recurso cuja queda sozinha derruba o sistema inteiro. Eliminar pontos únicos de falha como esse é o assunto do resto desta lição, e existem 2 níveis diferentes de "eliminado", não 1.
Recapitulando: as peças que você já tem
Você já tem as 2 ferramentas que tornam essa eliminação possível. Zonas de disponibilidade dão locais fisicamente separados para distribuir instâncias, então uma noite ruim em 1 data center não derruba tudo de uma vez. Um load balancer fica na frente dessas instâncias, faz health check em cada uma e só envia tráfego para as que ainda respondem. Junte as 2 coisas, instâncias distribuídas em várias zonas atrás de um load balancer, e repetir a falha das 2h da manhã deixa de ser catastrófico. O que ela vira em seguida, um pequeno soluço ou nada, depende de quanta capacidade extra já estava rodando no momento da falha.
Alta disponibilidade: continuar no ar durante uma interrupção breve
Deployments Multi-AZ do Amazon RDS mostram esse padrão com clareza. Uma instância de banco de dados primária cuida de toda leitura e escrita, enquanto um standby em outra zona de disponibilidade fica sincronizado em segundo plano, pronto, mas ocioso. Se o primário falha, o RDS detecta, promove o standby e reaponta o registro DNS do banco para ele, geralmente em 60 a 120 segundos, com 0 perda de dados. Durante esses 60 a 120 segundos, porém, as conexões com o banco caem ou ficam na fila.
Isso é alta disponibilidade: o sistema se recupera sozinho e rápido, mas a própria recuperação é uma lacuna visível, ainda que breve. A maioria das aplicações só precisa disso. Um minuto de erros de conexão durante uma falha rara de zona é um problema bem diferente da queda total que a rede de varejo com 1 instância sofreu.
Tolerância a falhas: continuar no ar sem interrupção nenhuma
Volte para a API de checkout, agora redesenhada. Digamos que ela precisa de 6 instâncias rodando para atender a carga normal. Distribuídas em 2 zonas de disponibilidade, 3 instâncias em cada, isso já é altamente disponível: perca 1 zona, e as 3 instâncias sobreviventes mantêm o checkout no ar, só que com metade da capacidade até novas instâncias subirem atrás delas. Distribua em 3 zonas de disponibilidade, com 3 instâncias em cada, 9 no total, e perder qualquer 1 zona ainda deixa 6 instâncias no ar, exatamente a capacidade que o checkout precisa. Nada muda para quem usa o sistema. Isso é tolerância a falhas: o sistema nunca ficou realmente sem capacidade, porque as instâncias "extras" já estavam rodando e já atendiam tráfego antes da falha acontecer.
A comparação resume a distinção inteira em 1 imagem: um design altamente disponível tem redundância suficiente para sobreviver a uma falha, e um design tolerante a falhas tem redundância suficiente para que sobreviver a ela não produza nenhuma queda para sobreviver. Tolerância a falhas se parece mais com um pneu autovedante, que mantém o carro andando na velocidade normal mesmo furado, do que com um estepe, que só coloca o carro em movimento de novo depois de parar para trocar, e é exatamente esse o visual da janela de recuperação da alta disponibilidade. Force a comparação além desse ponto, porém, e ela quebra: um estepe é barato para carregar sem uso, enquanto a capacidade tolerante a falhas cobra de você toda hora em que fica ociosa, esperando uma falha que talvez nunca aconteça.
Onde a redundância precisa chegar: cada camada, não só a computação
Um sistema só é tão disponível quanto sua camada menos redundante. Distribuir a camada de computação entre zonas não adianta nada se o banco de dados, o load balancer ou o DNS ainda são um ponto único de falha por baixo.
| Camada | Ponto único de falha | Padrão de redundância |
|---|---|---|
| Computação | 1 instância | Várias instâncias em múltiplas AZs atrás de um load balancer |
| Load balancer | 1 nó de load balancer | Load balancers gerenciados já rodam de forma redundante entre AZs por padrão |
| Banco de dados | 1 instância de banco de dados | Deployment Multi-AZ com failover automático |
| DNS | 1 registro estático sem consciência de saúde | Roteamento DNS com health check, que para de apontar para um alvo com falha |
Provedores de nuvem constroem load balancers gerenciados e health checks de DNS gerenciados já redundantes por padrão, então as camadas que um time normalmente precisa projetar de forma explícita são computação e banco de dados.
Ativo-ativo versus ativo-passivo
Os 2 padrões de redundância acima têm nome, e a diferença entre eles reaparece mais adiante neste tópico. Ativo-ativo significa que toda réplica atende tráfego ao mesmo tempo, do jeito que um load balancer distribui requisições entre todas as instâncias saudáveis agora mesmo, não só quando algo falha. Ativo-passivo significa que 1 lado faz o trabalho enquanto o outro fica sincronizado e ocioso, pronto para assumir, do jeito que um standby Multi-AZ do RDS se comporta.
| Ativo-ativo | Ativo-passivo | |
|---|---|---|
| Quem atende tráfego normalmente | Todas as réplicas, ao mesmo tempo | Só 1 primário |
| Como se comporta uma falha | As réplicas restantes já absorvem a carga | Um failover promove o standby |
| Uso típico | Camadas de computação com load balancer | Bancos de dados gerenciados Multi-AZ |
Nenhum padrão é melhor por natureza. Camadas de computação costumam ser ativo-ativo porque dividir requisições sem estado entre várias instâncias idênticas é simples. Bancos de dados costumam ser ativo-passivo porque manter toda réplica gravável ao mesmo tempo levanta questões difíceis de consistência que um único escritor ativo evita.
Equívoco: "multi-AZ" não significa automaticamente "tolerante a falhas"
É tentador ouvir "distribuído em várias zonas de disponibilidade" e presumir que isso resolve a questão da confiabilidade. Resolve só metade dela. Multi-AZ garante que uma falha em 1 zona não derruba todas as instâncias. Não diz nada sobre se a capacidade sobrevivente é suficiente para continuar atendendo sua carga total sem nenhuma queda. Um time que distribui 6 instâncias em 2 zonas melhorou de verdade a disponibilidade em relação a um deployment de zona única, mas não se tornou tolerante a falhas, e presumir o contrário é exatamente a lacuna que aparece como uma falta de capacidade não planejada no próximo evento de zona.
Dicas para a prova: lendo uma questão de alta disponibilidade versus tolerância a falhas
| O cenário diz... | Aponta para |
|---|---|
| "Interrupção breve é aceitável", "recuperação automática", "downtime mínimo" | Alta disponibilidade |
| "Nenhuma interrupção", "contínuo", "os usuários não podem perceber" | Tolerância a falhas |
| "1 instância", "1 data center", "sem redundância" | Um ponto único de falha para eliminar primeiro |
| "Standby", "failover", "promovido" | Ativo-passivo |
| "Todas as instâncias atendem tráfego ao mesmo tempo" | Ativo-ativo |
A armadilha a observar: um cenário que descreve um deployment multi-AZ sólido e pergunta se ele é tolerante a falhas. Confira a conta de capacidade, não só o número de zonas, antes de responder.
Onde isso deixa você
As 2 abordagens partem do mesmo movimento, eliminar um ponto único de falha, e depois divergem em quanta capacidade extra você está disposto a manter rodando e pagando o tempo todo. Alta disponibilidade tolera uma janela de recuperação curta e automática; tolerância a falhas elimina essa janela mantendo a capacidade redundante já ativa. A maioria das aplicações só precisa da primeira. A próxima lição sai de continuar no ar durante uma falha e vai para uma pergunta relacionada, mas separada: depois de decidir quanta capacidade um sistema precisa, quem decide quando adicionar mais dela, e quando tirar de novo.
