Design clássico · Pleno
Venda de ingressos para grande evento (Ticketmaster)
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. Uma bilheteria online mostra eventos, deixa buscar e vende ingressos. O difícil não é listar eventos: é, quando muita gente quer o mesmo assento ao mesmo tempo, entregar cada assento a uma só pessoa sem derrubar o sistema.
01 · CONTEXTO E REQUISITOS
Vender o mesmo assento uma única vez
Uma bilheteria online mostra eventos, deixa buscar e vende ingressos. O difícil não é listar eventos: é, quando muita gente quer o mesmo assento ao mesmo tempo, entregar cada assento a uma só pessoa sem derrubar o sistema. Este caso é um clássico de entrevista de levantamento de requisitos.
Os requisitos funcionais de núcleo são três: ver eventos, buscar eventos e reservar ingressos. Entre os não funcionais, a fonte separa dois comportamentos: busca e visualização priorizam disponibilidade, enquanto a reserva prioriza consistência, para nunca haver venda dupla. Há ainda metas de escala e latência: suportar um evento muito popular, busca rápida e um sistema dominado por leituras.
02 · ENTIDADES E PRIMEIRO DESENHO
Do evento ao assento
O modelo de dados gira em torno de evento, local, artista, ingresso e reserva. A fonte lista entidades como evento, artista e local, além de usuário, ingresso e reserva. Cada assento do local vira um ingresso quando o evento é criado, e o cliente combina o mapa do local com o estado de cada ingresso para desenhar a seleção de assentos.
A API tem consultas de leitura (ver um evento, buscar eventos) e uma operação de escrita que reserva: um POST em /bookings com o identificador do ingresso escolhido.
A pessoa abre a página de um evento; a requisição passa pelo gateway e chega ao serviço de eventos.
O serviço de eventos lê evento, local e ingressos do banco para montar o mapa de assentos.
Ao escolher um assento, a requisição de reserva vai pelo gateway ao serviço de reservas.
O serviço de reservas grava no mesmo banco. A pergunta aberta é como impedir que duas pessoas levem o mesmo assento.
Esta primeira versão separa leitura de reserva, mas ainda não diz como segurar um assento enquanto a pessoa paga. É o problema central do caso.
03 · RESERVAR SEM VENDA DUPLA
Da trava no banco ao bloqueio com validade
A primeira ideia de muitos candidatos é travar a linha do ingresso no banco enquanto a pessoa paga. A fonte a trata como má solução: bloqueios longos sobrecarregam o banco e aumentam o risco de contenção e deadlock.
Uma alternativa melhor marca o ingresso como reservado, com hora de vencimento, e usa uma tarefa periódica para devolver os vencidos ao estoque. O limite, segundo a fonte, é a defasagem entre o vencimento e a correção da linha, ruim para eventos populares. Uma variação evita a tarefa: uma transação curta aceita o ingresso se ele estiver disponível ou com reserva já vencida, o que garante um único reservante.
A solução que a fonte adota é um bloqueio distribuído com TTL em Redis. O Redis expira chaves sozinho, e o comando de gravar a chave só se ela não existir, com validade, é atômico: só um cliente a consegue. O banco passa a ter só dois estados de ingresso, e as reservas em andamento vivem no Redis.
| Critério | Trava de linha no banco | Status com vencimento | Bloqueio distribuído com TTL |
|---|---|---|---|
| Como segura o ingresso | Mantém a transação aberta durante o pagamento | Marca o ingresso como reservado com hora de vencimento | Grava uma chave com validade em um armazenamento em memória |
| Limite apontado | Contenção, deadlock e carga no banco | Defasagem na devolução dos vencidos | Exige um componente a mais e uma leitura extra para mostrar o mapa |
| Liberação | Só ao fim da transação | Pela tarefa periódica ou pela checagem na próxima reserva | Automática, quando a chave expira |
A pessoa escolhe um assento no mapa; a reserva chega ao serviço de reservas.
O serviço de reservas tenta gravar no Redis uma chave com o identificador do ingresso e validade de dez minutos. Só uma tentativa vence.
Com o bloqueio obtido, o serviço grava uma reserva em andamento no banco e a pessoa segue para o pagamento.
Quando o pagamento é confirmado, o ingresso vira vendido, a reserva fica confirmada e o bloqueio é liberado.
Se o tempo acaba sem pagamento, o Redis libera a chave sozinho e o ingresso volta a ficar disponível.
Dois detalhes de robustez. O aviso de pagamento chega por webhook que pode ser reenviado, então o tratador deve ser idempotente. E se a reserva vencer durante o pagamento, a fonte propõe reembolso automático, além de definir um TTL generoso.
04 · LEITURA E BUSCA
Cache, índice de busca e CDN
Como o tráfego é dominado por leituras, o serviço de eventos fica sem estado e escala horizontalmente atrás de um balanceador. Dados muito lidos e pouco alterados, como detalhes do evento e do local, são bons candidatos a cache, em estilo read-through: uma falha do cache lê o banco e atualiza o cache.
Para a busca, a fonte parte de índices no banco e chega a um motor de busca textual, como o Elasticsearch, mantido em sincronia com o banco SQL por captura de mudanças (CDC). Para buscas repetidas, resultados podem ficar em cache e, quando fizer sentido, em uma CDN mais perto de quem busca.
A busca ou a página do evento passa primeiro pela CDN, que pode já ter o resultado de uma busca repetida.
No caminho de leitura, o serviço de eventos consulta o cache. Se o evento está lá, responde sem tocar no banco.
Se não está, o serviço lê do banco e grava o resultado no cache para as próximas pessoas.
A busca por texto vai ao índice de busca, que responde mais rápido que varrer o banco.
As mudanças do banco são copiadas para o índice por captura de mudanças, para as buscas não ficarem velhas.
05 · EVENTO MUITO POPULAR
Mapa em tempo real e fila virtual
Para o mapa de assentos refletir reservas de outras pessoas sem recarregar a página, a fonte propõe empurrar atualizações ao cliente com Server-Sent Events. Funciona bem para eventos moderados; em eventos extremamente populares, o mapa esvazia num instante e a experiência continua ruim.
Para esse caso, a fonte propõe uma fila de espera virtual habilitada por administradores. A fila fica na frente do serviço de reservas, mantém uma conexão persistente com quem espera, tira pessoas da frente aos poucos e registra as admitidas. O serviço de reservas consulta esse registro e rejeita quem não passou pela fila.
Em um evento disputado, a pessoa que pede a página de reserva entra primeiro na fila virtual, antes de ver o mapa.
O serviço de fila mantém uma conexão aberta e guarda a ordem de chegada no Redis para informar a posição.
Aos poucos, pessoas saem da frente da fila e são marcadas como admitidas, com validade.
O serviço de reservas confere o registro de admitidos e rejeita quem não passou pela fila.
Quem foi admitido segue o fluxo normal: bloqueio com validade, reserva em andamento e pagamento.
06 · LIMITES DO DESENHO
O que ainda pode dar errado
O bloqueio com TTL tem um custo de leitura: o mapa precisa combinar o banco com o Redis, o que acrescenta uma ida ao Redis no caminho de leitura. Há também a escolha do TTL: se vencer durante o pagamento, a compra falha e o reembolso entra em cena. A fonte recomenda um TTL generoso e, melhor ainda, estender o bloqueio quando o pagamento começa.
Perguntas frequentes
O que é Venda de ingressos para grande evento (Ticketmaster)?
Projeto de entrevista clássico. Pontos centrais: reservas e concorrência e controle de sobrecarga.
O que o design de Venda de ingressos para grande evento (Ticketmaster) cobre?
Ele está organizado nestas seções: Vender o mesmo assento uma única vez, Do evento ao assento, Da trava no banco ao bloqueio com validade, Cache, índice de busca e CDN, Mapa em tempo real e fila virtual e O que ainda pode dar errado.
Quanto tempo leva Venda de ingressos para grande evento (Ticketmaster) e qual é o nível?
Leva cerca de 14 minutos para ler e tem nível Pleno.
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.