Pular para o conteudo principal

Concorrência por recurso no backend sem lock espalhado

Quando vários fluxos disputam o mesmo recurso, sair distribuindo lock em todo lugar costuma esconder o problema em vez de organizá-lo.

Andrews Ribeiro

Andrews Ribeiro

Founder & Engineer

O problema

Muita contenção no backend não é “concorrência abstrata”.

É disputa por um recurso bem concreto:

  • o mesmo pedido
  • o mesmo saldo
  • a mesma vaga
  • o mesmo arquivo

Quando isso aparece, o time costuma reagir assim:

  • coloca um lock aqui
  • mais um lock ali
  • mais uma checagem no worker

Logo ninguém sabe mais:

  • quem coordena de verdade
  • qual recurso está sendo protegido
  • o que acontece se o lock quebrar

Modelo mental

A pergunta útil não é:

“onde eu coloco um lock?”

A pergunta útil é:

“qual recurso não pode ser manipulado ao mesmo tempo sem coordenação?”

Quando isso fica claro, a solução costuma aparecer melhor.

Às vezes é:

  • lock
  • fila por chave
  • controle otimista
  • compare-and-set
  • restrição no banco

Lock é só uma das opções.

Exemplo simples

Imagine cancelamento e captura do mesmo pagamento acontecendo quase juntos.

Se dois fluxos diferentes podem:

  • capturar
  • cancelar
  • estornar

então o recurso disputado não é “o método”.

É o pagamento.

Essa leitura muda o desenho.

Talvez a coordenação precise acontecer por payment_id, e não espalhada em três lugares diferentes.

O erro comum

O erro comum é distribuir proteção demais e responsabilidade de menos.

Exemplos:

  • helper faz lock sem contrato claro
  • worker faz outro lock por cima
  • banco ainda tenta garantir por fora

Agora o sistema tem coordenação duplicada, difícil de explicar e pior ainda de operar.

Quando algo trava, ninguém sabe qual camada é a dona da regra.

Onde a coordenação costuma funcionar melhor

Normalmente, a coordenação precisa morar perto do ponto em que a decisão crítica acontece.

Pode ser:

  • no banco, se a contenção é local e transacional
  • em processamento serial por chave, se o fluxo é assíncrono
  • em controle otimista, se conflito é raro e barato de revalidar

O que costuma falhar é esconder a regra em utilitário genérico.

Lock também é operação

Se usar lock, ainda falta responder:

  • quem é o dono?
  • quando expira?
  • como renova?
  • o que acontece se o processo morrer?

Sem isso, lock não é coordenação.

É apenas esperança com nome técnico.

Como um senior pensa

Quem decide melhor costuma perguntar:

  • qual recurso está em disputa de verdade?
  • o conflito é frequente ou raro?
  • a decisão precisa ser síncrona ou pode ser serializada depois?
  • qual mecanismo deixa o comportamento mais explicável e recuperável?

Essas perguntas normalmente levam a desenho melhor do que “coloca um distributed lock”.

Ângulo de entrevista

Esse tema aparece em backend, pagamentos, estoque, filas e system design.

O entrevistador quer ver se você entende:

  • que contenção precisa de dono claro
  • que lock não é resposta automática
  • que coordenação e recuperação andam juntas

Resposta forte costuma soar assim:

“Eu modelaria primeiro qual recurso está sendo disputado e em qual ponto a decisão crítica acontece. A partir daí escolheria entre lock, fila por chave ou controle otimista. O objetivo não é espalhar proteção; é centralizar a coordenação no lugar certo.”

Takeaway direto

Concorrência madura não é sair travando tudo.

É escolher onde o recurso realmente é coordenado.

Resumo rápido

O que vale manter na cabeça

Checklist de pratica

Use isto ao responder

Você concluiu este artigo

Próximo artigo Escrita dupla interna com verificação Artigo anterior Controle de admissão no backend: quando rejeitar cedo é melhor do que falhar tarde

Continue explorando

Artigos relacionados