4

A CazéTV bugou o Instagram

Ontem, Cabo Verde fez história. Na estreia da seleção africana em Copas do Mundo, o goleiro Vozinha, de 40 anos, segurou um empate sem gols contra a Espanha, uma das favoritas ao título, e foi eleito o melhor jogador da partida pela Fifa.

Fora de campo, aconteceu outra coisa curiosa. Durante a transmissão da CazéTV, a audiência fez um mutirão para seguir o goleiro no Instagram. Em menos de um dia, o perfil saltou de cerca de 50 mil para mais de 8 milhões de seguidores. E foi aí que começaram a circular vídeos de pessoas dando refresh no perfil e vendo o número de seguidores subir e descer, como se o Instagram tivesse travado.

Spoiler: não travou. O que essas pessoas viram é um dos conceitos mais clássicos de arquitetura de sistemas distribuídos, e um dos temas mais cobrados em entrevistas de system design em grandes empresas. O nome dele é consistência eventual.

Por que o número subia e descia

Pensa na diferença entre duas operações no Instagram:

  • Ler o número de seguidores de um perfil (read) acontece o tempo todo. Toda vez que alguém abre o perfil, é uma leitura.
  • Seguir alguém (write) acontece numa fração ínfima dessa frequência.

Num perfil que recebe milhões de visitas, seria inviável recalcular o total de seguidores a cada acesso, varrendo a tabela inteira de quem segue quem. Em vez disso, esse número é pré-calculado e guardado em cache, replicado em várias cópias espalhadas pela infraestrutura. Isso garante duas coisas que redes sociais priorizam acima de quase tudo: resposta rápida (baixa latência) e disponibilidade (se uma réplica cai, as outras respondem).

O detalhe é que essas réplicas não são atualizadas todas no mesmo instante. Quando você dá refresh no perfil, sua requisição passa por um load balancer, que te direciona para uma réplica qualquer. Em um momento de pico, como dezenas de milhares de follows por minuto, cada réplica está num ponto diferente do processo de atualização: uma já contabilizou a última leva de seguidores, a outra ainda está alguns milhares atrás.

Resultado: a cada refresh você lê uma cópia diferente, cada uma mais ou menos atrasada. Por isso o número parece "andar pra trás". Você não está vendo o total real oscilar, está vendo fotos diferentes, tiradas em momentos diferentes, de um número que ainda não convergiu.

No caso da Meta, esse contador vive num sistema chamado TAO, uma camada de cache distribuída construída em cima do MySQL, justamente para servir leituras do grafo social em escala absurda. Mas o princípio vale para qualquer rede social grande.

Quando o pico passa e as atualizações alcançam todas as réplicas, o número estabiliza. Não foi bug. Foi um sistema bem projetado funcionando exatamente como foi desenhado.

Diagram

Consistência não é "tudo ou nada"

Aqui está a parte que rende artigo, e entrevista: consistência eventual é só uma das pontas de um espectro. Entre "todo mundo sempre vê o valor mais atualizado" e "cada um vê o que der", existem vários níveis intermediários. Cada produto escolhe o nível que faz sentido para o seu caso.

Vou do mais fraco ao mais forte, com um exemplo brasileiro de cada.

Consistência eventual

Se as escritas pararem, em algum momento todas as réplicas convergem para o mesmo valor. Sem garantia de ordem nem de quando. É barato e rápido, mas o cliente pode ler valores velhos ou ver o número regredir.

Exemplo: os seguidores do Vozinha. Likes, visualizações e contadores de redes sociais em geral. Ninguém abre reclamação no Procon porque o contador mostrou alguns milhares a mais ou a menos por meio segundo. É o caso de uso perfeito para o modelo mais barato.

Read-your-writes (leia suas próprias escritas)

Garante que você sempre enxerga as suas próprias alterações na hora, mesmo que outras pessoas ainda vejam o valor antigo.

Exemplo: a avaliação que você deixa numa compra do Mercado Livre. Quando você avalia o vendedor e atualiza a página, a sua avaliação precisa aparecer imediatamente, senão você acha que não salvou e escreve de novo. Para os outros compradores, tudo bem se ela demorar alguns segundos para propagar.

Monotonic reads (leituras monotônicas)

Uma vez que você leu um valor, as próximas leituras nunca retornam algo mais antigo. O valor só anda para frente, nunca para trás.

Exemplo: o rastreamento de um pedido na Shopee ou nos Correios. Se o status já mostrou "saiu para entrega", ele não pode voltar para "em trânsito" no próximo refresh, isso geraria pânico no cliente. Repara que é exatamente a falta dessa garantia que produziu a oscilação dos seguidores do Vozinha.

Consistência causal

Operações que têm relação de causa e efeito são vistas na ordem certa por todo mundo. Operações sem relação entre si podem aparecer em ordens diferentes para pessoas diferentes.

Exemplo: uma thread de comentários ou respostas no WhatsApp ou no X. Se alguém pergunta "vai chover hoje?" e outra pessoa responde "leva o guarda-chuva então", ninguém pode ver a resposta aparecer antes da pergunta. A relação de causa precisa ser respeitada. Já duas mensagens sem relação entre si, enviadas ao mesmo tempo, podem aparecer em ordens ligeiramente diferentes sem que ninguém perceba.

Linearizabilidade (consistência forte)

Toda operação se comporta como se acontecesse instantaneamente, num único ponto do tempo, e todo mundo enxerga a mesma ordem global. É como se existisse uma única cópia da verdade. Em troca, é o modelo mais caro: exige coordenação entre réplicas, o que custa latência e disponibilidade.

Exemplo: uma transferência via Pix no Nubank. Quando você manda R$ 100, o débito na sua conta e o crédito na conta do destinatário precisam refletir o saldo real na mesma hora e do mesmo jeito para todos. Não pode existir uma réplica achando que o dinheiro ainda é seu e outra achando que já saiu, senão você gastaria o mesmo valor duas vezes (o famoso double spending). Por isso o banco aceita pagar o custo de coordenação que o contador de seguidores se recusa a pagar. O mesmo vale para a venda de ingressos de um show concorrido: a mesma cadeira não pode ser vendida para duas pessoas.

Resumo

ModeloGarantiaExemplo no BrasilO que acontece se faltar
Consistência eventualConverge com o tempoSeguidores e likes no InstagramNúmero oscila por alguns segundos (tudo bem)
Read-your-writesVocê vê suas escritas na horaAvaliação no Mercado LivreVocê acha que não salvou e duplica
Monotonic readsValor nunca regrideRastreio na Shopee / CorreiosStatus "volta no tempo" e assusta
Consistência causalCausa antes do efeitoRespostas no WhatsApp / XResposta aparece antes da pergunta
LinearizabilidadeCópia única da verdadePix no Nubank, ingressosSaldo errado, double spending

A escolha é de negócio, não de qualidade técnica

A lição que fica é a mais importante: o nível de consistência não mede o quão bom é o engenheiro. É uma decisão de produto.

O time do Instagram não foi preguiçoso ao deixar o contador de seguidores eventual, e o time do Nubank não é superior por escolher linearizabilidade. Cada um pagou o preço certo para o seu problema. Consistência forte custa latência e disponibilidade. Consistência fraca custa precisão temporária. Errar para um lado deixa o app lento à toa. Errar para o outro vende a mesma cadeira duas vezes, ou deixa alguém gastar o dobro.

Da próxima vez que um número "bugar" na sua frente numa rede social, lembra do Vozinha. Provavelmente não é bug. É alguém que decidiu, de propósito, que velocidade vale mais que precisão naquele caso específico. E essa decisão, tomada bem, é o que faz um sistema aguentar o efeito Cazé sem cair.


E você? Já esbarrou (ou já implementou) um caso desses no seu dia a dia? Um contador que oscilava, um saldo que precisava bater na hora, um cache que te traiu bem na hora da demo? Conta aí nos comentários qual modelo de consistência você escolheria, e por quê. Quero ver os casos de vocês.

Carregando publicação patrocinada...