Design clássico · Sênior
Flash sale (venda relâmpago)
Projeto de entrevista clássico. Pontos centrais: reservas e concorrência e controle de sobrecarga.
Resposta curta
Projeto de entrevista clássico. Pontos centrais: reservas e concorrência e controle de sobrecarga. A venda relâmpago isola um pedaço difícil do comércio eletrônico: vender uma quantidade muito limitada de estoque sob demanda extrema. A meta é deixar os compradores disputarem as unidades de forma justa e concluírem a compra sem nunca vender além do estoque.
01 · CONTEXTO
Poucas unidades, muita gente
A venda relâmpago isola um pedaço difícil do comércio eletrônico: vender uma quantidade muito limitada de estoque sob demanda extrema. A meta é deixar os compradores disputarem as unidades de forma justa e concluírem a compra sem nunca vender além do estoque.
O fluxo ganha uma etapa entre ver o produto e pagar: a reserva da unidade. O pagamento passa por um terceiro e leva segundos, e não se pode manter o estoque preso numa transação aberta de banco durante todo esse tempo. A reserva tira a unidade de circulação de imediato e deixa o acerto do dinheiro para depois.
O material público lista quatro aprofundamentos que formam o roteiro deste caso: manter a consistência sob contenção extrema, liberar com eficiência as reservas vencidas, lidar com milhões de usuários chegando de uma vez e tornar justo o acesso ao estoque limitado.
02 · CORRIDA
O contador que fica negativo
A forma ingênua de vender é ler a contagem disponível, conferir se é maior que zero e depois decrementá-la. Para um comprador isolado isso está correto. Com dois compradores no mesmo instante, os dois leem a mesma contagem, os dois concluem que há unidade para vender e os dois seguem para a cobrança do cartão.
Quando as duas gravações chegam, a primeira leva a contagem a zero e a segunda decrementa de novo, e a contagem fica negativa. O vendedor termina com um reembolso a fazer e dois clientes insatisfeitos.
Dois compradores pedem a última unidade quase no mesmo instante.
Os dois pedidos leem a mesma contagem e veem uma unidade disponível.
Cada um conclui que há unidade para vender e segue para a cobrança.
A primeira gravação leva a contagem a zero e a segunda decrementa de novo, deixando-a negativa.
Uma linha de contagem única obriga todo checkout do item a atualizar a mesma linha, o que prepara a próxima seção.
03 · LINHA QUENTE
Uma linha só, uma fila só
Na descrição do Hello Interview para o trabalho da Shopify, a tentativa óbvia num banco relacional era uma linha por item com um contador de quantidade. Todo checkout de um item popular tinha de atualizar a mesma linha, e o InnoDB, motor do MySQL, concede o travamento da linha a uma transação por vez, de modo que os demais compradores esperam. Milhares de checkouts do mesmo item colapsavam num único travamento.
A saída documentada espalha a disputa. Para reservar unidades, o sistema seleciona e trava linhas disponíveis e as retira do conjunto. O recurso SKIP LOCKED faz o MySQL pular linhas travadas e procurar outra disponível; assim, dois compradores do mesmo item travam linhas diferentes e confirmam em paralelo, em vez de esperar atrás de um contador compartilhado.
O ganho tem um limite. Um item com muito estoque poderia gerar centenas de milhares de linhas quase ociosas, por isso há um teto de linhas por item e um processo de reposição que mantém o conjunto abastecido.
Dois compradores do mesmo item chegam ao checkout.
Numa transação curta, o checkout seleciona e trava linhas disponíveis e as retira do conjunto.
O segundo comprador passa por cima das linhas já travadas e trava outras, sem esperar.
A reserva fica gravada como uma linha com prazo, e os travamentos só existem dentro das transações curtas que a tocam.
Um processo de reposição mantém o conjunto abastecido quando ele esvazia.
Uma corrida pode esvaziar o conjunto antes de a reposição chegar; então a própria reserva reabastece o conjunto na hora e tenta de novo.
| Aspecto | Contador único | Uma linha por unidade |
|---|---|---|
| Como o estoque é guardado | Uma linha por item com um contador de quantidade | Linhas disponíveis que o checkout trava e retira do conjunto |
| Sob disputa | Milhares de checkouts do item colapsam num único travamento | Compradores travam linhas diferentes e confirmam em paralelo |
| O que se paga | Todo checkout do item atualiza a mesma linha | Um processo novo de reposição para operar, monitorar e acionar, cuja falha típica é o conjunto vazio no meio da venda |
04 · ATOMICIDADE
Contar num lugar, vender em outro
O mesmo relato mostra por que o contador pode não poder ficar fora do banco que guarda o estoque. Antes, o Redis registrava as unidades reservadas temporariamente e o MySQL registrava as unidades que o comerciante de fato tinha. Como mecanismo de concorrência, o Redis funcionava, mas as duas gravações aconteciam em bancos diferentes e não podiam ser confirmadas juntas.
Os dois erros custam dinheiro: vender a última unidade a dois compradores obriga a cancelar um pedido, e esconder uma unidade que ainda está no armazém faz o comerciante perder uma venda. Se o sistema atualiza o MySQL e cai antes de limpar a reserva no Redis, a compra está concluída, mas o Redis ainda trata aquelas unidades como reservadas, e o sistema esconde estoque que está disponível. Na ordem inversa o erro é o oposto: a reserva é limpa, a queda vem antes da atualização e as unidades voltam à venda mesmo já vendidas. Trocar a ordem só muda qual falha é possível.
O commit em duas fases também não resolve: exigiria que os dois bancos participassem do mesmo protocolo de coordenação, o que o Redis não podia fazer.
05 · PRAZO
Reservas que ninguém avisa que acabaram
Reservar não é comprar. Se o pagamento falha ou o comprador sai do checkout, há um sinal explícito que libera a reserva. Se o comprador apenas fecha o notebook, nenhum sinal chega, e, se nada devolver as unidades, a venda aparece como esgotada enquanto o armazém ainda tem estoque. Por isso o prazo precisa viver nos dados, e algo ainda em execução tem de agir quando ele passa.
Com um contador em Redis, a saída tentadora é um TTL, mas um TTL na chave do contador apagaria o contador inteiro, e não a reserva de um comprador. Uma chave por reserva também não ajuda: o Redis não tem um jeito rápido de obter a contagem a partir de um monte de chaves por reserva.
Para o desenho em MySQL, o Hello Interview diz que o post da Shopify não informa o que ela fez e dá um palpite próprio: guardar a reserva como uma linha com prazo e contar como ativas só as reservas ainda não vencidas. Vencido o prazo, a reserva deixa de contar e a próxima reposição devolve a capacidade. Uma rotina de limpeza ainda é desejável, mas é coleta de lixo, não correção.
06 · ENTRADA
A multidão antes do banco
Mesmo um desenho correto de estoque precisa de proteção contra milhões de usuários chegando de uma vez, que o material lista como aprofundamento à parte. Uma sala de espera virtual encaminha o excesso de usuários a uma fila personalizada, preservando a experiência e protegendo os servidores de origem de serem sobrecarregados com requisições.
Uma sala de espera bem-feita lembra o estado de cada visitante, para que ninguém perca o lugar na fila nem tenha de reentrar se sair do site, e abre vagas mais depressa acompanhando o fluxo de entrada e de saída.
Além da fila, o próprio servidor precisa se proteger. Vazão é tudo o que chega; a vazão útil (goodput) é a parte tratada sem erros e com latência baixa o bastante para o cliente aproveitar a resposta. Descartar carga permite manter a vazão útil mesmo quando a carga oferecida cresce, e rejeitar cedo é o ponto mais barato para descartar, ao custo de visibilidade.
Uma multidão tenta abrir a venda ao mesmo tempo.
A sala de espera encaminha o excesso de usuários a uma fila personalizada, em vez de deixá-lo chegar à origem.
A sala guarda o estado de cada visitante, que assim mantém o lugar na fila.
Só o tráfego admitido chega ao checkout, que ainda pode descartar cedo o que exceder sua capacidade.
O banco de estoque recebe apenas a carga que sobrou depois dessas camadas.
O material público trata a justiça do acesso ao estoque limitado como um aprofundamento à parte, ao lado da consistência, da expiração das reservas e da multidão.
Perguntas frequentes
O que é Flash sale (venda relâmpago)?
Projeto de entrevista clássico. Pontos centrais: reservas e concorrência e controle de sobrecarga.
O que o design de Flash sale (venda relâmpago) cobre?
Ele está organizado nestas seções: Poucas unidades, muita gente, O contador que fica negativo, Uma linha só, uma fila só, Contar num lugar, vender em outro, Reservas que ninguém avisa que acabaram e A multidão antes do banco.
Quanto tempo leva Flash sale (venda relâmpago) e qual é o nível?
Leva cerca de 16 minutos para ler e tem nível Sênior.
Agora projete você mesmo
Rode este caso como uma entrevista na escola de System Design: você toma as decisões, o tutor as questiona e você vê a nota do seu desenho.