Pular para o conteudo principal

Locks, Filas e Retries: Quando Usar Cada um

Como escolher entre segurar disputa, serializar trabalho ou tentar de novo sem transformar todo problema concorrente na mesma solução.

Andrews Ribeiro

Andrews Ribeiro

Founder & Engineer

O problema

Quando o sistema quebra sob concorrência, muita gente sai aplicando remedio sem nomear a doenca.

Joga retry em bug de duplicidade. Joga lock em fluxo que precisava de fila. Joga fila em operação que só precisava de uma escrita atomica.

O resultado costuma ser um sistema mais lento, mais difícil de operar e ainda incorreto.

Modelo mental

Esses mecanismos não sao sinonimos.

Pense assim:

  • lock responde: “como eu evito que duas execuções mexam nisso ao mesmo tempo?”
  • fila responde: “como eu tiro esse trabalho do caminho principal e controlo o ritmo ou a ordem?”
  • retry responde: “como eu tento de novo quando a falha parece temporária?”

Cada um compra uma garantia diferente.

Se você usa a ferramenta certa para a pergunta errada, o sistema continua quebrando.

Quebrando o problema

Quando lock faz sentido

Lock entra quando existe recurso compartilhado e disputa real.

Exemplos:

  • ultima vaga
  • mesmo saldo
  • mesmo item de estoque
  • mesma janela de agendamento

O papel dele e impedir execuções simultâneas sobre o mesmo alvo enquanto a decisão crítica acontece.

Mas lock cobra preco:

  • espera
  • risco de timeout
  • risco de deadlock se mal desenhado
  • menor throughput em recurso muito disputado

Por isso lock não e resposta padrão para tudo.

Quando fila faz sentido

Fila entra quando o problema não e só disputa local, mas formato do trabalho.

Ela ajuda quando você quer:

  • processar depois
  • absorver pico
  • desacoplar produtor de consumidor
  • serializar trabalho por chave ou por partição

Fila pode inclusive reduzir disputa se você decide processar certos eventos em ordem controlada.

Mas fila não substitui corretude de negócio sozinha.

Se a mensagem repetir ou chegar fora da ordem que você imaginou, idempotencia e desenho de consumidor continuam importantes.

Quando retry faz sentido

Retry e útil quando a falha parece temporária:

  • timeout de rede
  • erro transitorio de dependência
  • lock otimista perdido
  • serviço indisponivel por um instante

Retry não deveria ser usado cegamente.

Pergunta boa:

se eu repetir agora, tenho chance real de sucesso sem causar efeito colateral duplo?

Se a resposta for não, retry pode piorar o incidente.

Exemplo simples

Imagine tres problemas diferentes.

Caso 1: ultima unidade de estoque

Duas compras tentam reservar o mesmo item.

Aqui você precisa proteger corretude da decisão. Lock, operação atomica ou controle transacional fazem sentido.

Retry sozinho não resolve venda dupla.

Caso 2: gerar miniaturas de imagem apos upload

O usuário não precisa esperar tudo no request.

Aqui fila faz mais sentido. Ela tira trabalho pesado do caminho principal e deixa workers processarem no ritmo certo.

Lock seria exagero. Retry pode existir dentro do consumidor, mas não e a peca principal.

Caso 3: chamada para serviço de pagamento com timeout transitivo

Se a operação for segura para repetição, retry com backoff pode fazer sentido.

Mas se a chamada puder cobrar duas vezes e não houver idempotencia, retry vira risco de dano.

Perceba a diferença:

  • lock protege disputa
  • fila organiza processamento
  • retry lida com falha temporária

Erros comuns

  • Colocar retry em tudo como se repetição sempre fosse segura.
  • Usar lock onde uma operação atomica simples resolveria melhor.
  • Jogar fluxo em fila só para “escalar” sem pensar em observabilidade e reprocessamento.
  • Tratar fila como garantia de exactly-once.
  • Esquecer backoff e tempestade de retries durante incidente.

Também e comum esquecer que essas pecas podem coexistir.

Um consumidor de fila pode usar retry para falha transitiva e ainda depender de idempotencia para não duplicar efeito.

Como um senior pensa

Quem tem mais experiência costuma perguntar primeiro qual verdade precisa ser protegida.

Algo como:

“Estou tentando proteger exclusao mutua, controlar formato do trabalho ou sobreviver a falha temporária?”

Essa pergunta limpa a escolha.

Se a dor e disputa, você pensa em lock ou atomicidade. Se a dor e acoplamento e pico, fila entra forte. Se a dor e instabilidade momentanea, retry entra, mas com critério.

O que o entrevistador quer ver

Em entrevista, o avaliador quer ver se você escolhe mecanismo por tipo de problema e se entende o custo de cada um.

Sinaliza maturidade quando você:

  • não trata retry como martelo universal
  • sabe dizer por que lock reduz concorrência para ganhar corretude
  • sabe quando fila muda o formato do fluxo
  • menciona backoff, idempotencia e observabilidade junto de retry

Uma resposta forte costuma soar assim:

“Primeiro eu nomeio a necessidade. Se preciso proteger recurso disputado, penso em lock ou atomicidade. Se preciso desacoplar e controlar ritmo, fila. Se a falha e temporária e repetir e seguro, retry com backoff.”

Ferramenta madura não e a mais sofisticada. E a que protege a regra certa pelo menor custo razoavel.

Resumo rápido

O que vale manter na cabeça

Checklist de pratica

Use isto ao responder

Você concluiu este artigo

Próximo artigo Race condition na prática Artigo anterior Jobs Assíncronos, Filas e Workers: o Fluxo Completo

Continue explorando

Artigos relacionados