Voltar ao blog

Estabilidade na coleta de dados em grande escala: problemas que aparecem ao escalar

Uma tarefa pode funcionar com dez alvos e perder confiabilidade ao chegar a milhares. Classificação de falhas e deduplicação, limitação de taxa e concorrência, retomada, falhas de saída de rede, verificações de consistência e algumas métricas-chave tornam-se críticas em escala.

Um script de coleta pode funcionar bem com dez alvos e começar a perder taxa de sucesso quando é ampliado para milhares. Você adiciona tentativas, troca proxies, ajusta a concorrência, mas os problemas continuam voltando. Ao investigar mais a fundo, o gargalo muitas vezes não está na lógica de parsing, e sim em algumas camadas de engenharia que não foram construídas. Em pequena escala, esses problemas podem nem aparecer.

Classifique as falhas antes para que as novas tentativas façam sentido

Falhas são inevitáveis na coleta. O ponto importante é classificá-las: oscilações de rede e reinicializações de conexão podem ser tentadas novamente de imediato; limitação temporária de taxa deve ser seguida de backoff antes de nova tentativa; se uma mudança na estrutura da página fizer o parsing retornar vazio, nem dez mil tentativas resolverão, então é preciso registrar e alertar; se o alvo simplesmente não existe, marque a tarefa como concluída; se um ambiente ou uma saída de rede não iniciar, troque por outro e tente de novo.

Tentar tudo novamente sem distinção é um dos erros mais comuns. Isso esconde em loops problemas que exigem intervenção humana e, ao mesmo tempo, desperdiça cota e capacidade de saída. O backoff também é necessário: o intervalo entre tentativas deve aumentar; caso contrário, um lote inteiro voltará na mesma janela de tempo e agravará ainda mais a limitação.

As novas tentativas levam diretamente à deduplicação. Uma tarefa pode ser executada várias vezes por causa dos retries, então cada tarefa precisa de um identificador único e estável — por exemplo, o valor após normalizar a URL — e as gravações devem ser idempotentes com base nesse identificador. Senão, quanto mais tentativas, mais dados sujos.

Limitação de taxa e concorrência são coisas diferentes

Aumentar a concorrência não garante maior throughput. Três limites atuam ao mesmo tempo: quanto o site-alvo suporta antes de aplicar limitação e reduzir o throughput total, a memória e a CPU da máquina local e se um único ambiente ou sessão consegue executar várias tarefas simultaneamente.

Uma abordagem mais estável é começar com baixa concorrência e aumentar a carga gradualmente, observando juntos a taxa de sucesso e o tempo de resposta para encontrar o ponto em que o desempenho piora de forma clara. Limitação de taxa é outro assunto: ela controla o ritmo de acesso ao mesmo alvo e não é a mesma coisa que concorrência global. Quando um lote distribui tarefas por vários sites, cada site precisa do seu próprio ritmo.

A retomada depende de estado persistente

Em uma tarefa que roda por horas, uma interrupção é normal; recomeçar tudo do zero costuma custar caro demais. O requisito é persistir o estado: pendente, em execução, concluída, além do número de tentativas, do próximo horário permitido para execução e do tipo de erro. Quando o processo inicia, a fila deve ser restaurada a partir do armazenamento, em vez de ser reconstruída em memória.

Manter a fila apenas na memória é uma implementação muito comum que parece funcionar. Quando o processo cai, todas as tarefas que aguardavam na fila são perdidas e as contagens deixam de fechar.

Trate separadamente falhas de proxy e de saída de rede

Uma saída bloqueada pelo alvo, um proxy offline ou um nó regional instável são ocorrências contínuas em escala. Não são exceções raras, e sim parte da rotina. Trate as saídas como recursos substituíveis: quando uma tarefa falhar, determine primeiro se o alvo está limitando a taxa ou se a saída está indisponível; faça backoff no primeiro caso e troque a saída antes de tentar novamente no segundo. Registre também a taxa de falhas de cada saída e retire os grupos que apresentarem degradação evidente.

Por outro lado, se todas as tarefas compartilham uma única saída, uma tarefa pode derrubar o caminho e afetar todas as demais. Para investigar, será preciso voltar pelos logs até descobrir qual tarefa causou o problema.

Verificação de consistência dos dados

Uma execução concluída não significa que os dados estejam corretos. Depois de gravar, você deve conseguir responder a algumas perguntas: o número de tarefas concluídas corresponde ao número de linhas armazenadas, qual é a proporção de resultados de parsing vazios, a taxa de ausência em campos críticos subiu de forma anormal, quantas linhas duplicadas existem?

Essas verificações não precisam ser complexas. Uma amostragem por lote é suficiente, mas alguém precisa analisar o resultado. Em grande escala, dados incorretos podem ser mais problemáticos do que não ter dados.

Quais métricas acompanhar

Não é preciso acumular métricas. Algumas que reflitam a saúde do sistema são suficientes.

  • Taxa de sucesso e distribuição dos tipos de falha, para ver quais erros estão aumentando
  • Tamanho da fila e tempo médio de espera; um acúmulo que cresce continuamente indica desequilíbrio entre entrada e capacidade de processamento
  • Número de ambientes ativos e processos relacionados; crescimento prolongado em uma só direção costuma indicar vazamento na liberação de recursos
  • Produção por unidade de tempo, para avaliar se a limitação de taxa está reduzindo o throughput
  • Taxa de falha das saídas, para decidir se um grupo de nós deve ser substituído

Se qualquer uma dessas métricas continuar mudando em uma única direção por muito tempo, verifique primeiro a liberação de recursos e a lógica de novas tentativas.

Separe a camada de ambiente

Vistos em conjunto, esses pontos levam à mesma conclusão: a camada de ambiente precisa ser gerenciada separadamente dos scripts. O pooling de ambientes exige agendamento centralizado em vez de ambientes espalhados em scripts individuais; a liberação de recursos exige estado consultável em vez de cada script tentar se recuperar sozinho; trocar de ambiente ou de saída durante uma nova tentativa só funciona quando os ambientes podem ser agendados de forma independente.

Os scripts cuidam da lógica; a camada de ambiente cuida dos recursos e da identidade. Nesse tipo de arquitetura, o PurpleMark ocupa essa camada, oferecendo recursos de ambiente que podem ser criados em lote, vinculados a saídas de rede independentes e consultados por status.

Limites de conformidade

Capacidade de escalar não significa poder coletar qualquer coisa livremente. Respeite as regras robots e os termos de serviço do site-alvo, não colete informações pessoais, não contorne medidas técnicas de proteção e controle a frequência das solicitações para não afetar o funcionamento normal do serviço. Estabilidade é uma questão técnica; ter permissão para coletar é outra. As duas condições precisam ser atendidas.