trilha

System Design/04 - Cloud Design Patterns/Messaging2 min

Sequential Convoy

Perguntas-guia
  • Que problema isso resolve?
  • Quando usar / quando NÃO usar?
  • Qual o principal trade-off?
  • Como isso falha em produção?

Conceito

Garantir ordem dentro de um grupo de mensagens relacionadas, mantendo paralelismo entre grupos.

cliente-A:  A1 → A2 → A3     processados em ordem
cliente-B:  B1 → B2          em paralelo com A, e em ordem entre si
cliente-C:  C1               idem

A chave de agrupamento é o mecanismo: Message Group ID no SQS FIFO, partition key no Kafka e no Kinesis, session ID no Service Bus. Mensagens com a mesma chave vão para a mesma partição e são processadas sequencialmente por um único consumidor.

Trade-offs

É o meio-termo entre dois extremos ruins.

Ordem global (uma fila, um consumidor) garante tudo e elimina o paralelismo — o throughput fica limitado a um consumidor, independentemente de quanta capacidade exista.

Sem ordem (Competing Consumers puro) escala perfeitamente e permite que a atualização de um registro seja processada antes da criação dele.

O convoy sequencial dá ordem onde ela importa e paralelismo onde ela não importa. O limite fica sendo o número de chaves distintas: com 10 mil clientes, há até 10 mil fluxos paralelos.

Os custos:

Uma mensagem lenta bloqueia seu grupo inteiro. É head-of-line blocking por chave. Se o processamento de A1 trava, A2 e A3 esperam — mesmo com workers ociosos. Timeout por mensagem é obrigatório.

Mensagem venenosa é pior aqui. Sem DLQ, uma mensagem que sempre falha bloqueia permanentemente todo o grupo, não apenas a si mesma.

Chave mal escolhida desbalanceia. Uma chave que concentra a maior parte do tráfego cria uma partição quente, e o paralelismo teórico não se realiza. É o mesmo problema de shard key em Sharding.

E há um limite estrutural: a ordem só é garantida dentro da chave. Se a lógica de negócio precisa de ordem entre chaves diferentes, o padrão não resolve.

Exemplo prático

Eventos de conta bancária, onde a ordem por conta é indispensável e a ordem entre contas é irrelevante.

MessageGroupId = conta_id

Depósito e saque da mesma conta são processados na ordem correta. Contas diferentes são processadas simultaneamente por workers diferentes.

Sem o agrupamento, um saque poderia ser processado antes do depósito que o cobre — e o saldo ficaria negativo por uma questão de escalonamento, não de negócio.

Com ordem global, o sistema processaria uma conta por vez: correto e inutilizável em qualquer escala.

Relacionado


Parte de Messaging · roadmap.sh/system-design

Buscar

Busca por título, seção e texto das notas