Orivel Orivel
Abrir menu

Projetar um Encurtador de URL para 10.000 Requisições por Segundo

Compare as respostas dos modelos para esta tarefa de benchmark em Design de sistemas e reveja pontuações, comentários e exemplos relacionados.

Entre ou cadastre-se para usar curtidas e favoritos. Cadastrar

X f L

Índice

Visão geral da tarefa

Gêneros de comparação

Design de sistemas

Modelo criador da tarefa

Modelos participantes

Modelos avaliadores

Enunciado da tarefa

Desenhe um serviço de encurtamento de URL (similar em espírito a um produto do tipo 'tiny link') que possa operar com confiabilidade em escala. Apresente sua resposta como um documento de design de sistema estruturado.

Requisitos funcionais:

  • Os usuários submetem uma URL longa e recebem um link curto (por exemplo, um código de 7 caracteres).
  • Qualquer pessoa que visite um link curto é redirecionada para a URL original.
  • Apelidos personalizados opcionais solicitados pelos usuários devem ser atendidos se disponív...
Mostrar mais

Desenhe um serviço de encurtamento de URL (similar em espírito a um produto do tipo 'tiny link') que possa operar com confiabilidade em escala. Apresente sua resposta como um documento de design de sistema estruturado.

Requisitos funcionais:

  • Os usuários submetem uma URL longa e recebem um link curto (por exemplo, um código de 7 caracteres).
  • Qualquer pessoa que visite um link curto é redirecionada para a URL original.
  • Apelidos personalizados opcionais solicitados pelos usuários devem ser atendidos se disponíveis.
  • Análise básica de cliques: contagem total de cliques por link curto.

Restrições não funcionais (projetar considerando explicitamente estes números):

  • Tráfego de pico: 10.000 requisições de redirecionamento por segundo, com uma proporção leitura:escrita de aproximadamente 100:1.
  • Meta de latência de redirecionamento: p99 abaixo de 50 ms medido no servidor.
  • Total de links armazenados ao longo de 5 anos: cerca de 30 bilhões.
  • Meta de disponibilidade de redirecionamento: 99,99% mensal.
  • Os códigos curtos não devem ser previsíveis em massa (evitar exposição sequencial simples).

Seu documento de design deve cobrir o seguinte, e para cada decisão significativa explique a troca (trade-off) que você está aceitando:

  1. Arquitetura de alto nível e fluxo de requisição para os caminhos de escrita (criação) e leitura (redirecionamento).
  2. Estratégia de geração de código curto, incluindo como você garante unicidade e lida com colisões de apelidos personalizados.
  3. Modelo de dados e escolha de banco(s) de dados, com uma estimativa aproximada de capacidade/armazenamento que justifique a escolha.
  4. Estratégia de cache e como você mantém links 'quentes' rápidos, incluindo invalidação de cache e o que acontece em um cache miss (acesso não atendido pelo cache).
  5. Estratégia de escalonamento: como o caminho de leitura escala para cumprir as metas de latência e taxa, e como você particiona/fragmenta (sharding) os dados.
  6. Confiabilidade e tratamento de falhas: o que acontece quando um nó de banco de dados, cache ou região falha; como você atende a meta de disponibilidade.
  7. Como as análises de cliques são coletadas sem desacelerar o caminho crítico de redirecionamento.

Declare quaisquer suposições que fizer. Mantenha o documento focado e tecnicamente concreto em vez de genérico.

Política de avaliação

Uma resposta forte aborda diretamente cada requisito numerado e vincula decisões às restrições declaradas (10K RPS, razão leitura:escrita 100:1, p99 abaixo de 50 ms, 30 bilhões de links, 99,99% de disponibilidade, códigos não previsíveis) em vez de oferecer jargão genérico de design de sistema.

Recompense respostas que: escolham um esquema de código curto apropriado e expliquem corretamente como unicidade e colisões de apelidos personalizados são tratadas; justifiquem a escolha do(s) banco(s) de dados com uma esti...

Mostrar mais

Uma resposta forte aborda diretamente cada requisito numerado e vincula decisões às restrições declaradas (10K RPS, razão leitura:escrita 100:1, p99 abaixo de 50 ms, 30 bilhões de links, 99,99% de disponibilidade, códigos não previsíveis) em vez de oferecer jargão genérico de design de sistema.

Recompense respostas que: escolham um esquema de código curto apropriado e expliquem corretamente como unicidade e colisões de apelidos personalizados são tratadas; justifiquem a escolha do(s) banco(s) de dados com uma estimativa plausível de armazenamento/capacidade derivada dos números fornecidos; descrevam uma camada de cache coerente com comportamento explícito em caso de cache miss e política de invalidação; expliquem particionamento/sharding e como o caminho de leitura atende latência e taxa; e descrevam um tratamento de falhas concreto (nó, cache e falha regional) que apoie credivelmente a meta de 99,99% de disponibilidade. As análises devem ser tratadas de forma assíncrona para que o caminho de redirecionamento permaneça rápido.

Valorize raciocínio claro sobre trade-offs: uma boa resposta nomeia as desvantagens de cada escolha principal (por exemplo, consistência vs. latência, custo de armazenamento vs. velocidade de leitura, previsibilidade vs. simplicidade) em vez de apresentar escolhas como soluções fáceis. Penalize respostas vagas, requisitos faltantes, números que contradizem as restrições, arquitetura internamente inconsistente ou alegações sem suporte. Respostas bem organizadas e suposições razoáveis devem ser recompensadas; extensão excessiva sem substância não deve ser.

Respostas

Resposta A: OpenAI GPT-5.6

Projeto do sistema: encurtador de URL escalável

Suposições

  1. Picos de tráfego de redirecionamento em 10.000 solicitações por segundo. Uma proporção nominal de 100:1 entre leitura e gravação implica aproximadamente 100 criações por segundo nesse pico.
  2. Trinta bilhões de links em cinco anos exigem aproximadamente 190 criações por segundo em média, portanto, o armazenamento e o caminho de gravação serão provisionados para pelo menos 1.000 criações por segundo para conciliar esse número e absorver rajadas.
  3. Links são imutáveis por padrão. Se a exclusão ou edição de destino for suportada posteriormente, ela us...
Mostrar resposta completa

Projeto do sistema: encurtador de URL escalável

Suposições

  1. Picos de tráfego de redirecionamento em 10.000 solicitações por segundo. Uma proporção nominal de 100:1 entre leitura e gravação implica aproximadamente 100 criações por segundo nesse pico.

  2. Trinta bilhões de links em cinco anos exigem aproximadamente 190 criações por segundo em média, portanto, o armazenamento e o caminho de gravação serão provisionados para pelo menos 1.000 criações por segundo para conciliar esse número e absorver rajadas.

  3. Links são imutáveis por padrão. Se a exclusão ou edição de destino for suportada posteriormente, ela usará versionamento explícito e invalidação de cache.

  4. Análises básicas podem ser eventualmente consistentes e podem perder um número muito pequeno de eventos durante falhas catastróficas. A correção do redirecionamento não depende de análises.

  5. Respostas de redirecionamento usam HTTP 302 ou 307 em vez de redirecionamentos permanentes 301, preservando o controle operacional e melhorando a visibilidade das análises.

  6. O serviço é executado ativo-a-ativo em pelo menos três regiões geográficas e usa um banco de dados de links replicado globalmente.

  7. Arquitetura de alto nível

Os componentes são DNS global ou roteamento Anycast, balanceadores de carga regionais, serviços de redirecionamento sem estado, serviços de criação sem estado, caches locais em memória, caches distribuídos regionais, um banco de dados de links particionado, um fluxo de eventos durável e processadores e armazenamento de análises.

Caminho de criação

  1. Um cliente envia a URL longa e um alias personalizado opcional para a região saudável mais próxima.
  2. A API autentica ou limita a taxa do chamador, valida a sintaxe da URL, limita o comprimento da URL, permite apenas esquemas suportados como HTTP e HTTPS e verifica aliases reservados.
  3. Para um link gerado automaticamente, o serviço cria um código criptograficamente aleatório. Para um alias personalizado, ele normaliza o alias de acordo com uma política documentada, sensível ou insensível a maiúsculas e minúsculas.
  4. O serviço de criação executa uma inserção condicional no banco de dados autoritativo: insere apenas se o código ou alias ainda não existir.
  5. Em uma colisão aleatória, ele gera outro código e tenta novamente. Em uma colisão de alias personalizado, ele retorna HTTP 409 sem alterar silenciosamente o alias solicitado.
  6. Após o banco de dados confirmar a gravação, o serviço insere o novo mapeamento no cache regional local e transmite uma mensagem de preenchimento ou invalidação de cache para outras regiões.
  7. Ele retorna a URL curta. Uma chave de idempotência de solicitação pode mapear solicitações repetidas do cliente para o mesmo resultado.

A gravação é confirmada apenas após um quórum ou commit de consenso. Isso adiciona latência de gravação entre zonas e, dependendo da configuração do banco de dados, entre regiões, mas cria uma garantia de exclusividade global autoritativa. A criação é muito menos sensível à latência do que o tráfego de redirecionamento.

Caminho de redirecionamento

  1. O roteamento global envia a solicitação para a região saudável mais próxima.
  2. O serviço de redirecionamento valida e extrai o código.
  3. Ele verifica um pequeno cache em memória. Se ausente, ele verifica o cache distribuído regional.
  4. Em uma falha de cache, ele executa uma consulta pontual em uma réplica local do banco de dados usando o código como chave primária.
  5. Se encontrado e ativo, ele preenche ambos os níveis de cache, emite assincronamente um evento de clique e retorna imediatamente uma resposta 302 ou 307 contendo o destino.
  6. Se ausente, retorna 404. Resultados negativos são cacheados apenas brevemente.

O caminho de redirecionamento não tem operação de análise síncrona e nenhum salto de rede entre regiões em condições normais. Serviços sem estado escalam horizontalmente atrás de balanceadores de carga regionais.

  1. Geração e exclusividade de código curto

Um espaço base62 de sete caracteres contém 62^7, aproximadamente 3,52 trilhões, de valores e pode tecnicamente conter 30 bilhões de links. No entanto, com 30 bilhões de links armazenados, cerca de 0,85% desse namespace é ocupado. Um scanner aleatório em massa descobriria, portanto, aproximadamente um link válido a cada 117 tentativas, o que não atende ao requisito de que os códigos sejam difíceis de adivinhar em massa.

O código padrão usará, portanto, 11 caracteres base62 seguros para URL gerados a partir de uma fonte aleatória criptograficamente segura. Isso fornece aproximadamente 65,5 bits e 5,2 × 10^19 possibilidades. Com 30 bilhões de links ativos, uma tentativa aleatória tem sucesso com probabilidade de cerca de 5,8 × 10^-10. Limitação de taxa e detecção de abuso restringem ainda mais a enumeração. A contrapartida é um link quatro caracteres mais longo. Aliases de sete caracteres ainda podem ser permitidos quando explicitamente escolhidos pelos usuários, mas eles não recebem a mesma garantia de não enumerabilidade.

A geração aleatória evita expor a ordem de criação e distribui as chaves uniformemente. Uma inserção condicional de chave primária é a autoridade final de exclusividade. Colisões de aniversário em todo o histórico completo são esperadas em um sistema aleatório, mas apenas colisões de candidatos simultâneas importam operacionalmente: cada inserção tentada é verificada e retentada. Na ocupação planejada do espaço de 11 caracteres, as retentativas são efetivamente inexistentes.

Uma alternativa seria criptografar ou aplicar uma permutação com chave a um número de sequência. Isso garante entradas geradas exclusivas, mas requer gerenciamento do ciclo de vida da chave e alocação de sequência. A geração aleatória mais inserção condicional é mais simples, remove a alocação centralizada de ID e é suficientemente eficiente nesse tamanho de namespace.

Aliases personalizados compartilham o mesmo namespace de chave primária que os códigos gerados. A normalização de alias ocorre antes da inserção, e uma inserção condicional globalmente consistente decide o vencedor de solicitações concorrentes. Caminhos reservados como saúde, API, admin e estático são rejeitados. Se os aliases não diferenciam maiúsculas de minúsculas, a forma normalizada em minúsculas é a chave, enquanto a forma de exibição solicitada pode ser armazenada separadamente.

  1. Modelo de dados e banco de dados

Os campos do registro de link autoritativo são:

código: chave primária
long_url: URL de destino
created_at: timestamp
owner_id: identificador de conta opcional
status: ativo, desativado ou excluído
ttl_or_expiry: opcional
version: valor monotonicamente crescente para invalidação de cache
custom_alias: booleano

As contagens de cliques não são atualizadas neste registro a cada redirecionamento, pois isso transformaria links populares em hotspots de gravação.

O armazenamento de links é um banco de dados de chave-valor distribuído e particionado otimizado para acesso por chave primária, como DynamoDB, Bigtable, Cassandra com consistência cuidadosamente gerenciada ou um sistema interno equivalente. Para gravações condicionais globalmente exclusivas, a implementação selecionada deve fornecer criação condicional linearizável para uma chave, nativamente ou por meio de líderes de consenso por shard. Junções relacionais e varreduras de intervalo não são necessárias no caminho de redirecionamento.

A chave de partição primária é um hash do código completo. A distribuição de hash evita hotspots cronológicos e espalha uniformemente códigos gerados e aliases personalizados. O keyspace lógico é dividido em milhares de shards virtuais, que são realocados à medida que os nós são adicionados. Cada shard tem pelo menos três réplicas entre zonas de disponibilidade, com réplicas adicionais entre regiões.

Estimativa de capacidade

Suponha uma URL média de 400 bytes e aproximadamente 200 bytes para chaves, metadados, codificação, índices e sobrecarga do mecanismo de armazenamento. Com cerca de 600 bytes por registro, 30 bilhões de registros exigem cerca de 18 TB de dados lógicos. Permitindo URLs mais longas, sobrecarga de compactação, marcadores de exclusão e margem operacional, orce 30 TB lógicos. Três réplicas duráveis exigem aproximadamente 90 TB, e backups, bem como cópias entre regiões, podem elevar a alocação da frota para cerca de 150–250 TB. Isso está bem dentro da faixa pretendida de bancos de dados de chave-valor particionados horizontalmente, mas é inadequado para uma única instância de banco de dados convencional.

A 10.000 redirecionamentos por segundo, mesmo uma falha completa de cache gera apenas 10.000 leituras pontuais aleatórias por segundo. O banco de dados é provisionado para pelo menos 20.000–30.000 leituras por segundo por região de serviço durante failover e pelo menos 1.000 criações condicionais por segundo. A capacidade é governada mais pelo tamanho do conjunto de dados, replicação e reserva de failover do que pelo throughput normal de solicitação.

Análises usam armazenamento separado. Um processador de fluxo grava contagens por código e por bucket de tempo em um banco de dados de chave-valor ou colunar de análises com um modelo como código mais dia ou hora como chave e contagem como valor. Um total compacto pode ser mantido assincronamente. Manter análises separadas evita que contadores de links populares contentionem com consultas de redirecionamento.

  1. Estratégia de cache

Cada processo de redirecionamento tem um cache em memória LRU limitado ou TinyLFU para os mapeamentos mais acessados. Um cluster regional compatível com Redis ou Memcached forma o segundo nível. Valores cacheados incluem destino, status, expiração e versão do registro.

Um alvo representativo é uma taxa de acerto de cache regional de 95–99%. A popularidade de URL semelhante à Lei de Zipf geralmente torna isso viável, mesmo que o corpus total seja muito grande. O cache armazena objetos quentes, não todos os 30 bilhões de links. Por exemplo, 100 milhões de entradas a aproximadamente 600 bytes cada consomem cerca de 60 GB antes da sobrecarga do cache e talvez 100–150 GB na prática, distribuídos por um cluster de cache regional.

Mapeamentos são imutáveis por padrão, portanto, entradas positivas podem ter um TTL longo, como 6–24 horas com jitter. Se a edição, desativação ou exclusão for suportada, a gravação autoritativa é confirmada primeiro e, em seguida, publica uma invalidação contendo o código e a nova versão para todas as regiões. TTLs mais curtos limitam o tempo de serviço de dados desatualizados se uma invalidação for perdida. Operações de desativação sensíveis à segurança também podem colocar uma pequena lista global de bloqueio em cada processo de redirecionamento.

Resultados negativos são cacheados por aproximadamente 5–30 segundos para resistir a varreduras repetidas. O caminho de criação invalida entradas de cache negativas após reivindicar com sucesso um código. O TTL negativo curto limita uma corrida na qual outra região cachead brevemente uma falha antes que a replicação ou invalidação chegue.

Em uma falha de cache, o serviço de redirecionamento lê a réplica do banco de dados regional e preenche ambos os níveis de cache. A coalescência de solicitações garante que falhas concorrentes para um código recém-popular emitam uma solicitação de banco de dados em vez de milhares. O jitter de TTL evita expiração sincronizada. O banco de dados é dimensionado para suportar toda a carga de 10.000 solicitações por segundo se o cache distribuído falhar, aceitando latência um pouco maior enquanto permanece funcional.

A contrapartida de TTLs de cache longos é a potencial desatualização após edições. Imutabilidade, invalidações versionadas e TTLs limitados tornam essa contrapartida explícita. A correção do redirecionamento para links recém-criados pode ser melhorada preenchendo síncronamente a região de criação e roteando uma leitura imediata para essa região quando necessário.

  1. Escalabilidade e latência

Serviços de redirecionamento são sem estado e escalam horizontalmente com base em solicitações por segundo, CPU e latência p99. Se uma instância processa com segurança 1.000 solicitações por segundo, cada região pode executar pelo menos 15–20 instâncias para uma carga de failover regional de 10.000 solicitações por segundo, mais margem para implantação e falha de zona. O dimensionamento real é estabelecido por meio de testes de carga.

Um orçamento normal de latência de acerto de cache é de aproximadamente 2–5 ms para balanceamento de carga e trabalho de aplicação, 1–3 ms para uma consulta em memória ou 2–8 ms para uma consulta de cache distribuído regional, e alguns milissegundos para construir a resposta. Um orçamento de falha de cache aloca aproximadamente 10–25 ms para uma consulta pontual local em banco de dados replicado. Esses orçamentos deixam espaço para manter o p99 do lado do servidor de origem abaixo de 50 ms.

Timeouts estritos por salto evitam que um cache ou réplica danificado consuma todo o orçamento de latência. O acesso ao cache pode ser limitado a aproximadamente 8 ms e o acesso ao banco de dados a aproximadamente 25–30 ms, com retentativas apenas quando houver orçamento suficiente. Leituras apressadas para uma segunda réplica local podem ser usadas para o percentil mais lento, mas elas são atrasadas e limitadas em taxa para evitar dobrar a carga normal.

Chaves são particionadas por hash entre shards virtuais. Códigos gerados aleatoriamente equilibram o tráfego, enquanto um link individual excepcionalmente quente é absorvido por caches em memória e regionais. Se uma chave quente atinge o banco de dados, a coalescência de solicitações e leituras replicadas evitam que um nó de armazenamento se torne o gargalo.

Autoscaling mantém capacidade suficiente para uma perda completa de zona de disponibilidade e pelo menos uma região recebendo tráfego redirecionado de um par falho. Regiões operam abaixo de aproximadamente 50–60% da capacidade de pico. A contrapartida é um custo ocioso mais alto em troca do objetivo de disponibilidade de 99,99%.

  1. Confiabilidade e tratamento de falhas

Meta de disponibilidade

Uma meta mensal de 99,99% permite cerca de 4,4 minutos de indisponibilidade em um mês de 30 dias. Nenhum cache de nó único, instância de aplicação, zona de disponibilidade ou região pode ser necessário para redirecionamentos.

Falha de instância de aplicação ou zona

Verificações de integridade removem instâncias com falha e balanceadores de carga distribuem solicitações entre pelo menos três zonas. Serviços usam implantações contínuas ou canário, esvaziamento de conexão e rollback automatizado. A capacidade regional sobrevive à perda de uma zona.

Falha de nó ou cluster de cache

Nós de cache são particionados e replicados dentro de uma região. Se um nó individual falhar, sua réplica assume. Se todo o cache estiver indisponível, os serviços de redirecionamento usam disjuntores, pulam chamadas de cache e consultam o banco de dados diretamente. A capacidade do banco de dados e os pools de conexão de aplicação são explicitamente provisionados para este modo. O controle de admissão protege o banco de dados contra tráfego de scanner ilimitado.

Falha de nó do banco de dados

Cada shard é replicado entre zonas usando quórum ou consenso. Um líder falho é substituído automaticamente; leituras usam outra réplica local saudável. Criações condicionais permanecem indisponíveis para um shard durante a breve eleição em vez de arriscar propriedade duplicada. Redirecionamentos podem continuar de réplicas e caches. Isso favorece a correção para criação enquanto preserva a disponibilidade de leitura.

Falha de região

Roteamento global baseado em integridade remove a região com falha e envia tráfego para a região saudável mais próxima. Cada região de serviço tem uma cópia replicada dos dados do link e infraestrutura independente de redirecionamento, cache e ingestão de eventos. A taxa de acerto de cache será inicialmente menor após o failover, portanto, regiões de standby mantêm caches aquecidos para links globalmente quentes e capacidade de banco de dados/leitura suficiente para o surto de cache frio.

Para códigos gerados, a replicação global pode ser assíncrona após uma inserção autoritativa com suporte de consenso se a arquitetura do banco de dados rotear cada chave para um shard de origem. Para aliases personalizados, a inserção condicional autoritativa deve permanecer globalmente serializada. Se um link recém-criado não atingiu uma região sobrevivente antes de uma perda catastrófica, o serviço pode retornar brevemente um erro retentável em vez de um mapeamento incorreto. Replicação síncrona mais forte entre regiões reduz essa janela de ponto de recuperação, mas aumenta a latência de criação. A configuração preferida confirma a criação de links entre réplicas em pelo menos duas regiões, pois as gravações são de volume relativamente baixo.

Backups e corrupção

O banco de dados usa checksums, recuperação de ponto no tempo, snapshots imutáveis e procedimentos de restauração testados regularmente. Exclusões usam marcadores de exclusão e um período de retenção em vez de remoção física imediata. Backups protegem contra corrupção lógica, mas não fazem parte do failover normal de redirecionamento.

Comportamento de sobrecarga

Limites de taxa se aplicam por origem, conta e padrão de escaneamento de código suspeito. Tráfego de criação e análise tem prioridade menor que redirecionamentos. Descarte de carga rejeita solicitações de criação abusivas ou excessivas antes que a capacidade de redirecionamento seja afetada. Disjuntores, filas limitadas e prazos evitam falhas em cascata.

  1. Análise de cliques

Após selecionar o destino do redirecionamento, o serviço cria um evento compacto contendo um ID de evento, código, timestamp, região e, opcionalmente, campos de referenciador ou user-agent grosseiros. Ele coloca o evento em um buffer assíncrono local limitado e retorna o redirecionamento sem esperar pela confirmação da análise.

Um coletor regional agrupa eventos em um fluxo replicado durável como Kafka, Pulsar ou Kinesis. Processadores de fluxo agregam eventos por código e bucket de tempo, e então gravam incrementos em lotes no armazenamento de análise. A compactação periódica produz contagens totais de cliques. Dashboards e APIs leem o armazenamento de análise, nunca a tabela de redirecionamento autoritativa.

IDs de evento permitem deduplicação downstream quando coletores tentam novamente. Particionar o fluxo diretamente por código concentraria um link viral em uma partição, portanto, a chave de ingestão pode ser código mais um stripe aleatório. Processadores primeiro agregam contadores com stripe e depois os mesclam. Isso permite que a análise de links quentes escale horizontalmente.

Um buffer assíncrono puramente em memória pode perder eventos se um processo de redirecionamento travar. Se uma durabilidade mais forte for necessária, cada host ou sidecar pode anexar lotes a um log local de escrita antecipada antes de encaminhá-los, mas as respostas de redirecionamento ainda não devem esperar pelo fluxo central. A contrapartida aceita para análises básicas é a consistência eventual e uma subcontagem pequena e medida durante falhas graves em troca de preservar a latência e a disponibilidade de redirecionamento.

Resultado

O caminho de redirecionamento normal é uma consulta de cache local seguida, apenas em caso de falha, por uma consulta de banco de dados de chave-valor particionado local. Códigos aleatórios de 11 caracteres evitam exposição sequencial e tornam adivinhações em massa bem-sucedidas impraticáveis. Inserções condicionais fornecem exclusividade, particionamento de hash suporta o corpus de 30 bilhões de registros, serviço regional ativo-a-ativo remove pontos únicos de falha regionais e análise assíncrona com stripe mantém as gravações de contador totalmente fora do caminho crítico de latência.

Resultado

#1 | Vencedor

Votos de vitória

3 / 3

Pontuação média

90
Modelos avaliadores Anthropic Claude Fable 5

Pontuação total

86

Comentário geral

A Resposta A é um documento de design excecionalmente completo e tecnicamente rigoroso. Liga cada decisão importante às restrições declaradas: deriva a taxa de escrita tanto da proporção de 100:1 como da figura de 30 mil milhões/5 anos e reconcilia a discrepância, calcula explicitamente que um espaço de 7 caracteres seria enumerável com uma ocupação de 0,85% (aproximadamente 1 acerto por 117 tentativas) e, portanto, avança para códigos aleatórios de 11 caracteres, fornece uma estimativa defensável de armazenamento por registo e a nível de frota (~18 TB lógicos, 90 TB replicados, 150-250 TB com backups), dá um orçamento concreto de latência p99 dividido em alocações por salto com tempos limite e leituras protegidas, e traduz 99,99% em 4,4 minutos/mês com tratamento de falhas em camadas para instâncias, cache, fragmentos de armazenamento de dados e regiões completas. As compensações são nomeadas honestamente ao longo do texto (códigos mais longos vs. enumerabilidade, latência de escrita entre regiões vs. unicidade global, capacidade ociosa vs. margem de falha, subcontagem de análises vs. latência de redirecionamento). As fraquezas são menores: a resposta é longa e densa, alguns números de dimensionamento são afirmados em vez de derivados, e um resumo em formato de diagrama melhoraria a capacidade de leitura. No geral, excede as expectativas de referência em quase todos os eixos.

Ver detalhes da avaliação

Qualidade da arquitetura

Peso 30%
87

Arquitetura ativa-ativa multirregional coerente com caminhos de criação/redirecionamento claramente separados, inserções condicionais para unicidade, cache de dois níveis com agregação de pedidos e uma rejeição quantificada correta de códigos de 7 caracteres (0,85% de ocupação torna a adivinhação em massa viável), levando a códigos CSPRNG de 11 caracteres. Cada decisão de componente está ligada a uma restrição. Dedução menor por densidade e algumas figuras de dimensionamento afirmadas em vez de derivadas.

Completude

Peso 20%
90

Todos os sete requisitos numerados são abordados com especificidades concretas: pressupostos declarados no início, reconciliação da taxa de escrita, análise completa da geração de códigos com política de colisão de aliases, matemática de armazenamento para 30 mil milhões de registos, comportamento explícito de cache-miss e invalidação, orçamento de latência por salto para p99 abaixo de 50 ms, tratamento de falhas em todas as camadas mapeado para o orçamento de 4,4 min/mês, e análises assíncronas segmentadas com compensações de durabilidade.

Análise de trade-offs

Peso 20%
85

As compensações são nomeadas e quantificadas ao longo do texto: 4 caracteres extras vs. enumerabilidade com matemática de probabilidade real, latência de escrita de consenso entre regiões vs. unicidade global, TTLs longos vs. obsolescência limitada por invalidações versionadas, capacidade ociosa abaixo de 50-60% de utilização vs. disponibilidade, e subcontagem de análises aceite vs. latência de redirecionamento. Alternativas (permutação chaveada de sequências) são consideradas e rejeitadas com razões.

Escalabilidade e confiabilidade

Peso 20%
85

História de escalabilidade concreta: fragmentos virtuais particionados por hash, dimensionamento de instâncias com margem de falha, armazenamento provisionado para absorver 10K RPS completos em caso de falha total da cache, leituras protegidas e tempos limite por salto, tradução de 99,99% para 4,4 minutos/mês, e tratamento de falhas em camadas cobrindo instância, zona, cache, eleição de líder de fragmento e perda completa de região com caches de standby quentes. A compensação de RPO para replicação entre regiões é discutida explicitamente.

Clareza

Peso 10%
80

Bem organizado com secções numeradas correspondentes ao prompt, pressupostos explícitos e um resumo final. A prosa é densa e longa, e algumas secções empacotam muitos números em parágrafos onde tabelas ou listas ajudariam, mas o fluxo do argumento é sempre rastreável.

Modelos avaliadores OpenAI GPT-5.5

Pontuação total

92

Comentário geral

A Resposta A é um projeto de sistema muito forte e concreto. Ela vincula explicitamente a arquitetura aos requisitos de 10.000 RPS, proporção de leitura/escrita de 100:1, p99 abaixo de 50 ms, corpus de 30 bilhões de links, meta de disponibilidade de 99,99% e requisito de não adivinhabilidade. Ela fornece fluxos de leitura e escrita coerentes, uma estratégia forte de códigos curtos, dimensionamento plausível de armazenamento, comportamento detalhado de cache, particionamento, confiabilidade multirregional e análise assíncrona. Sua principal fraqueza é que é um tanto elaborada, mas o detalhe é em sua maioria relevante e bem justificado.

Ver detalhes da avaliação

Qualidade da arquitetura

Peso 30%
92

A Resposta A fornece uma arquitetura ponta a ponta coerente com caminhos de criação e redirecionamento separados, cache local e distribuído, armazenamento autoritativo de chave-valor, streaming de eventos, regiões ativas-ativas e fluxos de solicitação normais e de falha claros. As escolhas de design se encaixam nas restrições de carga de trabalho e latência.

Completude

Peso 20%
95

A Resposta A aborda todas as seções exigidas em detalhes: fluxos de escrita/leitura, exclusividade, colisões de alias personalizados, estimativa de datastore e capacidade, comportamento de cache miss e invalidação, escalonamento e sharding, falhas de nó/cache/região e análise assíncrona. Ela também declara as suposições claramente.

Análise de trade-offs

Peso 20%
91

A Resposta A declara consistentemente trade-offs, como códigos mais longos versus resistência à enumeração, latência de escrita de quorum ou multirregional versus exclusividade, staleness de TTL de cache versus velocidade, custo de capacidade sobressalente versus disponibilidade e risco de perda de análise versus latência de redirecionamento.

Escalabilidade e confiabilidade

Peso 20%
92

A Resposta A fornece detalhes críveis de escalonamento e confiabilidade: escala horizontal sem estado, particionamento hash com shards virtuais, dimensionamento de cache e fallback, provisionamento de datastore para interrupção de cache, implantação multirregional ativa-ativa, failover regional, comportamento de quorum/consenso e análise assíncrona que evita escritas no caminho crítico.

Clareza

Peso 10%
90

A Resposta A é bem organizada, estruturada em torno das seções exigidas e usa números e mecanismos concretos. É longa, mas a estrutura torna o projeto fácil de seguir.

Modelos avaliadores Google Gemini 2.5 Pro

Pontuação total

92

Comentário geral

A resposta A fornece um design de sistema excepcional e abrangente. Ela se destaca ao abordar diretamente todas as restrições com escolhas técnicas específicas e bem fundamentadas. Sua análise da adivinhação de códigos curtos e a proposta de um código aleatório de 11 caracteres são um ponto forte fundamental. O planejamento de capacidade é detalhado e realista, e a arquitetura ativa-ativa multirregional oferece um caminho crível para atingir a meta de 99,99% de disponibilidade. A discussão sobre modos de falha em todos os níveis (nó, cache, região) é completa e demonstra um profundo entendimento na construção de sistemas resilientes.

Ver detalhes da avaliação

Qualidade da arquitetura

Peso 30%
90

A arquitetura é excelente. Propõe corretamente uma configuração ativa-ativa multirregional desde o início, o que é apropriado para a natureza global e os requisitos de alta disponibilidade. Os componentes são bem definidos e os fluxos de solicitação para os caminhos de leitura e gravação são detalhados e lógicos.

Completude

Peso 20%
95

A resposta é excepcionalmente completa, abordando todas as sete seções exigidas com detalhes significativos. Cada requisito funcional e não funcional é coberto com uma escolha de design específica.

Análise de trade-offs

Peso 20%
90

O raciocínio sobre trade-offs é um ponto forte importante desta resposta. Para quase todas as decisões significativas (por exemplo, comprimento do código, escolha do datastore, TTL do cache, estratégia de replicação), o trade-off específico é explicitamente declarado e justificado no contexto dos requisitos.

Escalabilidade e confiabilidade

Peso 20%
95

Esta é a parte mais forte da resposta. Identifica corretamente que códigos de 7 caracteres se tornam adivinháveis em uma escala de 30 bilhões e propõe uma solução robusta. A estimativa de capacidade é completa e realista. O plano de confiabilidade é excelente, cobrindo falhas nos níveis de instância, zona, cache, datastore e regional, fornecendo um caminho crível para 99,99% de disponibilidade.

Clareza

Peso 10%
85

O documento é muito bem estruturado, claro e tecnicamente denso. Segue precisamente o formato solicitado, facilitando a avaliação do design em relação aos requisitos.

Design de Sistema: Encurtador de URL (10K RPS)

Premissas:

  • Estamos a projetar inicialmente para uma única região, sendo multi-região uma melhoria futura.
  • O foco principal está no caminho de redirecionamento devido à proporção de leitura:escrita de 100:1.
  • Aliases personalizados são uma funcionalidade secundária e podem tolerar latência ligeiramente maior ou indisponibilidade ocasional em comparação com redirecionamentos padrão.
  • As análises de cliques não são estritamente em tempo real e podem ter um pequeno atraso.

1. Arquitetura de Alto Nível e Fluxo de Requisições

**Caminho de Escrit...

Mostrar resposta completa

Design de Sistema: Encurtador de URL (10K RPS)

Premissas:

  • Estamos a projetar inicialmente para uma única região, sendo multi-região uma melhoria futura.
  • O foco principal está no caminho de redirecionamento devido à proporção de leitura:escrita de 100:1.
  • Aliases personalizados são uma funcionalidade secundária e podem tolerar latência ligeiramente maior ou indisponibilidade ocasional em comparação com redirecionamentos padrão.
  • As análises de cliques não são estritamente em tempo real e podem ter um pequeno atraso.

1. Arquitetura de Alto Nível e Fluxo de Requisições

Caminho de Escrita (Criar Link Curto):

  1. API Gateway: Recebe a requisição POST com a URL longa e o alias personalizado opcional.
  2. Load Balancer: Distribui requisições de escrita para as instâncias da API do Serviço de Encurtamento de URL (US).
  3. API US (Serviço de Escrita):
    • Valida a URL de entrada.
    • Gera um código curto (ver Secção 2).
    • Se um alias personalizado for fornecido, tenta reservá-lo primeiro (ver Secção 2).
    • Persiste o mapeamento (short_code -> original_url, custom_alias -> short_code) no armazenamento de dados.
    • Retorna a URL curta gerada ao cliente.

Caminho de Leitura (Redirecionamento):

  1. API Gateway: Recebe a requisição GET para uma URL curta.
  2. Load Balancer: Distribui requisições de leitura para as instâncias da API US.
  3. API US (Serviço de Leitura):
    • Extrai o código curto do caminho da URL.
    • Consulta ao Cache: Verifica num cache distribuído (por exemplo, Redis Cluster) pelo código curto.
      • Cache Hit: Se encontrado, recupera a URL original e retorna uma resposta de redirecionamento HTTP 301/302.
      • Cache Miss: Se não encontrado, consulta o armazenamento de dados primário.
    • Consulta ao Armazenamento de Dados: Consulta o armazenamento de dados primário pela URL original associada ao código curto.
    • Atualização do Cache: Se encontrado no armazenamento de dados, a URL original é adicionada ao cache para requisições futuras.
    • Redirecionamento: Retorna uma resposta de redirecionamento HTTP 301/302 com a URL original.
    • Tratamento de Erros: Se não encontrado, retorna 404 Not Found.
  4. Análises de Cliques (Assíncronas): Um serviço ou mecanismo separado (ver Secção 7) regista eventos de clique de forma assíncrona.

Trade-offs:

  • Separação de Responsabilidades: Separar serviços de leitura e escrita permite escalonamento e otimização independentes. O caminho de leitura é otimizado para baixa latência e alto throughput.
  • API Gateway/Load Balancer: Introduz um ponto único de falha se não for configurado para alta disponibilidade, mas é essencial para escalar e gerir tráfego.
  • Penalidade de Cache Miss: Um cache miss incorre em latência maior devido à consulta ao armazenamento de dados, mas isto é mitigado por um cache grande e uma alta taxa de acertos.

2. Estratégia de Geração de Código Curto

Estratégia: Codificação Base62 com um Contador/Gerador de ID.

  1. Geração de ID: Usaremos um serviço distribuído de geração de IDs (por exemplo, semelhante ao Snowflake ou um serviço dedicado usando ZooKeeper/etcd) para gerar inteiros únicos, monotonamente crescentes, de 64 bits. Isto garante unicidade e evita colisões na origem.
    • Trade-off: Requer um serviço de geração de IDs altamente disponível e performante. Se falhar, novos links curtos não podem ser criados.
  2. Codificação Base62: Cada ID inteiro de 64 bits gerado é convertido numa string Base62 (0-9, a-z, A-Z). Um ID de 64 bits pode representar até 2^64 valores únicos. Os primeiros 6 caracteres podem representar ~68 mil milhões de valores únicos (62^6), e 7 caracteres podem representar ~4,1 biliões (62^7). Para 30 mil milhões de links ao longo de 5 anos, 7 caracteres são suficientes e fornecem amplo espaço para crescimento.
    • Trade-off: A codificação Base62 é ligeiramente mais complexa do que hashing simples, mas fornece URLs mais curtas e evita previsibilidade em comparação com IDs sequenciais.
  3. Aliases Personalizados:
    • Quando um utilizador solicita um alias personalizado (por exemplo, /my-link), o serviço de escrita verifica primeiro se o alias já está ocupado numa tabela/índice dedicado no armazenamento de dados (por exemplo, tabela custom_aliases que mapeia alias -> short_code).
    • Se o alias estiver disponível, é reservado e associado ao código curto recém-gerado.
    • Se o alias estiver ocupado, a API retorna um erro ao utilizador.
    • Tratamento de Colisões: A geração de ID e a codificação Base62 garantem unicidade para códigos curtos gerados. Aliases personalizados são tratados através de uma operação separada, atómica, de verificar-e-definir no armazenamento de dados para prevenir colisões.
    • Trade-off: Consultas de alias personalizado adicionam uma pequena sobrecarga ao caminho de escrita. A disponibilidade de aliases personalizados não é garantida.

Garantia de Unicidade: Alcançada pelo gerador distribuído de IDs. Cada ID é único, e a sua representação Base62 também será única.

Não previsível: IDs codificados em Base62 não são sequenciais e não revelam a ordem de criação nem o número total de links. São efetivamente strings com aparência aleatória.

3. Modelo de Dados e Armazenamento(s) de Dados

Escolha de Armazenamento de Dados: Um armazenamento distribuído NoSQL chave-valor (por exemplo, Cassandra, DynamoDB, ou uma BD relacional particionada como Vitess) para o mapeamento primário de links, e um sistema separado para análises.

Armazenamento de Dados Primário (Mapeamento de Links):

  • Esquema:

    • Tabela/coleção links:
      • short_code (Chave Primária, String, por exemplo, "aBcDeFg")
      • original_url (String)
      • created_at (Timestamp)
      • user_id (Opcional, para propriedade/gestão)
    • Tabela/coleção custom_aliases:
      • alias (Chave Primária, String, por exemplo, "my-link")
      • short_code (String, Chave Estrangeira para links.short_code)
  • Justificação do Tipo de Armazenamento de Dados: Um armazenamento distribuído NoSQL chave-valor é escolhido pela sua alta disponibilidade, escalabilidade horizontal e excelente desempenho de leitura para consultas por chave, o que é crítico para o caminho de redirecionamento. Pode lidar com a escala massiva de 30 mil milhões de entradas.

  • Estimativa de Capacidade/Armazenamento:

    • Tabela Links: 30 mil milhões de entradas.
      • short_code: ~7 bytes (Base62, 7 caracteres)
      • original_url: Média de 100 bytes (pode variar significativamente, assumindo a média)
      • created_at, user_id: ~10 bytes
      • Total por entrada: ~117 bytes. Vamos arredondar para 150 bytes para overhead e replicação.
      • Armazenamento total: 30 mil milhões * 150 bytes = 4,5 * 10^12 bytes = 4,5 TB.
    • Tabela Custom Aliases: Assumir que 10% dos links têm aliases personalizados (3 mil milhões).
      • alias: Média de 15 bytes (mais curto do que URLs longas).
      • short_code: ~7 bytes.
      • Total por entrada: ~22 bytes. Arredondar para 50 bytes para overhead.
      • Armazenamento total: 3 mil milhões * 50 bytes = 150 * 10^9 bytes = 0,15 TB.
    • Armazenamento Primário Total: ~4,65 TB. Isto é gerível para sistemas NoSQL distribuídos.
  • Particionamento/Sharding: O armazenamento de dados será particionado por short_code (para a tabela links) e alias (para a tabela custom_aliases). Isto permite uma distribuição uniforme de dados e carga entre nós.

Trade-offs:

  • NoSQL vs. SQL: Um armazenamento NoSQL é preferido pela flexibilidade de esquema e escalonamento horizontal. Uma BD relacional poderia funcionar, mas exigiria uma gestão de sharding mais complexa (por exemplo, Vitess).
  • Redundância de Dados: Armazenamentos NoSQL normalmente replicam dados para disponibilidade, aumentando os requisitos de armazenamento, mas melhorando a tolerância a falhas.
  • Tabela de Aliases Personalizados: Uma tabela separada é usada para verificar eficientemente a disponibilidade de aliases sem varrer a tabela principal links, o que seria ineficiente.

4. Estratégia de Cache

Estratégia: Cache Distribuído em Memória (por exemplo, Redis Cluster, Memcached).

  • O que Armazenar em Cache: Mapeamentos short_code para original_url frequentemente acedidos.
  • Chave de Cache: short_code (por exemplo, "aBcDeFg")
  • Valor de Cache: original_url (por exemplo, "https://www.verylongurl.com/...")
  • Tamanho do Cache: Dimensionado para conter uma parte significativa dos links quentes. Dado 10K RPS e proporção 100:1, esperamos milhões de links ativos por segundo. Um cache que contenha 1-5 milhões de entradas deve fornecer uma alta taxa de acertos para links quentes.
  • Invalidação de Cache:
    • Nenhuma invalidação explícita necessária para links padrão: Uma vez criados, os links são imutáveis. O mapeamento não muda.
    • Para aliases personalizados: Se um alias personalizado for alterado (normalmente não permitido, mas se fosse), o mapeamento antigo short_code -> original_url permaneceria no cache. No entanto, a prática padrão é que aliases personalizados sejam únicos e permanentes uma vez definidos. Se um link for apagado (não é uma funcionalidade comum para encurtadores de URL), então a entrada seria removida do cache.
  • Tratamento de Cache Miss:
    1. Num cache miss, a API US (Serviço de Leitura) consulta o armazenamento de dados primário pela original_url usando o short_code.
    2. Se encontrada no armazenamento de dados, a original_url é escrita de volta no cache com um Time-To-Live (TTL) (por exemplo, 24-48 horas) antes de ser retornada ao cliente.
    3. Se não encontrada no armazenamento de dados, um 404 é retornado, e nenhuma entrada é adicionada ao cache.

Trade-offs:

  • Desatualização do Cache: Cache baseado em TTL significa que há uma pequena janela em que um link pode ser atualizado (se atualizações fossem permitidas) e o cache ficaria desatualizado. No entanto, para links imutáveis, isto não é um problema.
  • Disponibilidade do Cache: O cache é um componente crítico. Se falhar, a latência aumenta significativamente devido a consultas ao armazenamento de dados, mas o serviço permanece disponível (embora mais lento).
  • Custo: Caches grandes em memória podem ser caros.

5. Estratégia de Escalonamento

Escalonamento do Caminho de Leitura (Redirecionamentos):

  • Servidores de API Stateless: As instâncias da API US que lidam com redirecionamentos são stateless. Isto permite-nos escalá-las horizontalmente de forma praticamente ilimitada atrás de um load balancer.
  • Cache Distribuído: Um cache distribuído particionado e replicado (como Redis Cluster) pode lidar com milhões de QPS e fornece baixa latência. É concebido para escalonamento horizontal.
  • Escalonamento do Armazenamento de Dados: O armazenamento de dados distribuído NoSQL escolhido (Cassandra, DynamoDB) é concebido para escalonamento horizontal. Podemos adicionar mais nós para aumentar throughput e capacidade.
  • Load Balancers: Load balancers em várias camadas (API Gateway, serviço-para-serviço interno) distribuem o tráfego uniformemente.

Particionamento/Sharding de Dados:

  • Sharding do Armazenamento de Dados: Como mencionado na Secção 3, o armazenamento de dados primário é particionado por short_code (ou por um hash dele) para a tabela links e por alias para a tabela custom_aliases. Isto distribui os dados e a carga de leitura/escrita por vários nós.
  • Sharding do Cache: O cache distribuído é inerentemente particionado, distribuindo chaves pelos seus nós.
  • Serviço de Geração de ID: Este serviço também deve ser escalável, potencialmente usando várias instâncias coordenadas por ZooKeeper/etcd ou por um protocolo de consenso distribuído.

Trade-offs:

  • Complexidade: Sharding e sistemas distribuídos adicionam complexidade operacional significativa.
  • Hotspots: Embora o sharding ajude, links extremamente populares ainda podem criar hotspots em shards específicos do cache ou partições do armazenamento de dados. Estratégias como hashing consistente ou balanceamento de carga mais avançado podem mitigar isto.

6. Confiabilidade e Tratamento de Falhas

Meta de Disponibilidade (99,99%): Requer redundância em todas as camadas.

  • Falha de Nó do Armazenamento de Dados:
    • Estratégia: Os dados são replicados por vários nós (por exemplo, 3-5 réplicas) e potencialmente por zonas de disponibilidade dentro de uma região.
    • Tratamento: O cluster de armazenamento de dados lida automaticamente com falhas de nós promovendo uma réplica e continuando a servir requisições. Leituras e escritas podem experimentar um breve pico de latência durante o failover, mas o serviço permanece disponível.
    • Trade-off: Aumento dos custos de armazenamento devido à replicação.
  • Falha de Nó de Cache:
    • Estratégia: Caches distribuídos como Redis Cluster são concebidos com replicação e sharding. Se um nó falhar, as suas réplicas podem assumir, ou os dados podem ser rebalanceados.
    • Tratamento: Cache misses aumentarão temporariamente à medida que o cache se reconstrói ou faz failover. O sistema recorrerá ao armazenamento de dados, levando a latência maior, mas disponibilidade contínua.
    • Trade-off: Degradação temporária de desempenho em caso de falha do cache.
  • Falha de Servidor de API:
    • Estratégia: Executar várias instâncias dos servidores stateless da API US atrás de load balancers.
    • Tratamento: Load balancers detetam instâncias não saudáveis e deixam de enviar tráfego para elas. O tráfego é automaticamente encaminhado para instâncias saudáveis.
    • Trade-off: Requer balanceamento de carga e health checking robustos.
  • Falha de Região:
    • Estratégia: Implementar o serviço em múltiplas Availability Zones (AZs) dentro de uma região. Para maior disponibilidade, pode ser implementada uma configuração multi-região active-active ou active-passive.
    • Tratamento: Se uma AZ falhar, o tráfego é encaminhado para AZs saudáveis. Se uma região inteira falhar, o tráfego é encaminhado para uma região secundária (requer balanceamento de carga global e replicação de dados).
    • Trade-off: Aumento significativo de complexidade e custo para implementações multi-região.

Cumprir a Meta de Disponibilidade: Redundância, failover automatizado e degradação graciosa (recorrer ao armazenamento de dados em caso de cache miss) são fundamentais. Monitorização e alertas são cruciais para detetar e responder rapidamente a falhas.

7. Recolha de Análises de Cliques

Estratégia: Processamento assíncrono para evitar impactar o caminho crítico de redirecionamento.

  1. Geração de Evento: Quando ocorre um redirecionamento (após a URL original ser recuperada e antes de a resposta de redirecionamento ser enviada), a API US (Serviço de Leitura) publica um evento leve

Resultado

#2

Votos de vitória

0 / 3

Pontuação média

53
Modelos avaliadores Anthropic Claude Fable 5

Pontuação total

55

Comentário geral

A Resposta B é um documento estruturado de forma competente, com títulos claros e marcadores explícitos de trade-offs, mas apresenta falhas substantivas significativas. Mais gravemente, o seu esquema de códigos curtos é internamente inconsistente: utiliza um contador monotónicamente crescente estilo Snowflake e depois afirma que a codificação Base62 torna os códigos não sequenciais e não adivinháveis, o que é falso — a codificação Base62 de IDs sequenciais permanece totalmente enumerável, violando diretamente a restrição declarada de não adivinhabilidade. A resposta também está truncada a meio de uma frase na Secção 7, deixando o pipeline de análise (um requisito numerado) incompleto. Outras fraquezas: a estimativa de armazenamento assume URLs de apenas 100 bytes em média (provavelmente baixo) e não multiplica concretamente a replicação; o objetivo de p99 abaixo de 50 ms nunca é abordado com um orçamento de latência; o raciocínio sobre o dimensionamento da cache (1-5 milhões de entradas) é afirmado sem derivação; e o tratamento de falhas regionais é descrito genericamente como uma possível melhoria futura em vez de ser projetado para a meta de 99,99%. Os seus pontos fortes são a organização legível, a intenção assíncrona correta para análise e escolhas razoáveis de datastore/sharding.

Ver detalhes da avaliação

Qualidade da arquitetura

Peso 30%
50

A forma geral (gateway, serviços sem estado, cache Redis, NoSQL sharded) é sensata, mas o design do código curto é internamente inconsistente: IDs Snowflake monotónicamente crescentes codificados em Base62 ainda são sequenciais e enumeráveis em massa, no entanto, a resposta afirma que são não adivinháveis. Isto falha diretamente uma restrição rígida declarada e é um erro de correção no centro do design. O resto da arquitetura é competente, mas genérico e de região única por defeito.

Completude

Peso 20%
50

As Secções 1-6 são cobertas a um nível razoável, mas a Secção 7 (análise de cliques) é cortada a meio de uma frase, deixando um requisito numerado incompleto. O objetivo de p99 abaixo de 50 ms nunca é abordado com qualquer orçamento de latência ou números, e a fiabilidade multirregional é adiada como uma melhoria futura em vez de ser projetada. A estimativa de armazenamento está presente, mas argumentavelmente subestima o tamanho do URL.

Análise de trade-offs

Peso 20%
60

Cada secção inclui um marcador explícito de trade-off, o que é um ponto forte genuíno, mas vários são superficiais ou genéricos (por exemplo, 'a complexidade aumenta', 'a replicação aumenta o custo'). O trade-off mais importante — IDs sequenciais vs. adivinhabilidade — é mal gerido: a desvantagem é negada em vez de ser reconhecida. Os trade-offs de cache e escalabilidade são declarados, mas não quantificados contra as restrições dadas.

Escalabilidade e confiabilidade

Peso 20%
55

História padrão de escalabilidade horizontal e replicação com sharding por short_code e failover automático, o que é adequado, mas genérico. O design é de região única com multirregional apenas mencionado como uma opção, o que apoia fracamente 99,99% de disponibilidade mensal. Não há quantificação da capacidade de failover, nenhum orçamento de latência, e o serviço de geração de IDs é reconhecido como um SPOF de criação sem uma mitigação concreta. A mitigação de hotspots é explicada superficialmente como 'estratégias como hashing consistente'.

Clareza

Peso 10%
65

A estrutura limpa em markdown com títulos, marcadores e chamadas de trade-offs por secção torna a leitura fácil. No entanto, o documento termina abruptamente a meio de uma frase na Secção 7, o que prejudica materialmente a experiência de leitura e deixa o requisito final por resolver.

Modelos avaliadores OpenAI GPT-5.5

Pontuação total

49

Comentário geral

A Resposta B apresenta uma arquitetura reconhecível de encurtador de URL com servidores de API, cache, datastore, sharding e intenção de análise assíncrona, mas é muito mais fraca em relação aos requisitos do benchmark. Assume inicialmente uma única região, apesar da meta de disponibilidade de 99,99%, afirma incorretamente que IDs gerados monotonicamente codificados em Base62 não são adivinháveis, fornece análise de latência limitada para a meta de p99 de 50 ms, tem uma estimativa de armazenamento questionável e a seção de análise está incompleta/truncada. Seus trade-offs estão presentes, mas muitas vezes genéricos.

Ver detalhes da avaliação

Qualidade da arquitetura

Peso 30%
52

A Resposta B possui os componentes básicos de um encurtador de URL, incluindo gateway de API, balanceadores de carga, cache, datastore e conceito de análise assíncrona. No entanto, a arquitetura é genérica, inicialmente de região única, carece de orçamento detalhado de latência e usa uma abordagem questionável de geração de código para o requisito de não adivinhabilidade.

Completude

Peso 20%
41

A Resposta B cobre muitos títulos superficialmente, mas vários requisitos estão incompletos ou subdesenvolvidos. Não atende adequadamente ao requisito de código não adivinhável, não projeta explicitamente para p99 abaixo de 50 ms, trata multi-região como trabalho futuro e sua seção de análise é cortada antes que o mecanismo real seja descrito.

Análise de trade-offs

Peso 20%
50

A Resposta B inclui marcadores de trade-off, mas muitos são genéricos e não estão profundamente ligados às restrições. Perde o trade-off crítico de que códigos derivados de IDs sequenciais ou monotônicos são mais fáceis de enumerar e subestima as implicações de disponibilidade de começar com um design de região única.

Escalabilidade e confiabilidade

Peso 20%
44

A Resposta B descreve escalonamento horizontal, cache particionado, datastore particionado e nós replicados, mas a história de confiabilidade não é suficiente para 99,99% porque assume inicialmente uma única região e deixa multi-região como um aprimoramento. Também não mostra como o caminho de leitura mantém p99 abaixo de 50 ms durante falhas ou misses de cache.

Clareza

Peso 10%
62

A Resposta B é geralmente legível e organizada pelas seções solicitadas, mas é menos precisa, contém algumas afirmações incorretas e a seção final de análise está visivelmente truncada, reduzindo a clareza e a completude.

Modelos avaliadores Google Gemini 2.5 Pro

Pontuação total

57

Comentário geral

A Resposta B apresenta um design padrão, mas falho e incompleto. Sua principal fraqueza é a escolha de um gerador de ID sequencial para códigos curtos, o que contradiz diretamente o requisito de não ser adivinhável. A suposição inicial de projetar para uma única região é inadequada para a meta de 99,99% de disponibilidade. Além disso, a estimativa de capacidade é excessivamente otimista e a seção final sobre análise está truncada, tornando a resposta incompleta. Embora os componentes básicos estejam corretos, o design falha em atender a várias restrições chave da solicitação.

Ver detalhes da avaliação

Qualidade da arquitetura

Peso 30%
65

A arquitetura é padrão e geralmente correta para um encurtador de URL básico. No entanto, a suposição inicial de um design de região única é uma fraqueza significativa, dada a exigência de 99,99% de disponibilidade, que é muito difícil de atender sem capacidades multirregionais ou, pelo menos, multizona robustas.

Completude

Peso 20%
40

A resposta está incompleta. A seção final sobre análise de cliques está truncada no meio de uma frase. Além disso, a discussão sobre falha regional, uma parte fundamental do requisito de confiabilidade, é tratada como um aprimoramento futuro em vez de uma parte central do design.

Análise de trade-offs

Peso 20%
60

A resposta inclui algum raciocínio sobre trade-offs, mas geralmente é genérico (por exemplo, "NoSQL vs. SQL", "Cache pode ser caro"). Falta a profundidade e especificidade da Resposta A, que vincula seus trade-offs diretamente às restrições da solicitação.

Escalabilidade e confiabilidade

Peso 20%
50

Esta área tem fraquezas significativas. A estratégia de geração de código proposta (Base62 de um contador) é adivinhável, violando um requisito central. A estimativa de capacidade é otimista. O plano de confiabilidade está subdesenvolvido, particularmente em relação à falha regional, tornando a meta de 99,99% de disponibilidade aparentemente inatingível com o design proposto.

Clareza

Peso 10%
70

A resposta é escrita de forma clara e bem estruturada com títulos. No entanto, o conteúdo carece da profundidade da Resposta A, e a seção final incompleta prejudica sua clareza geral.

Resumo comparativo

Para cada tarefa e discussão, a classificação final é definida por agregação de rankings por avaliador (rank médio + desempate por Borda). A pontuação média é exibida como referência.

Avaliadores: 3

Votos de vitória

3 / 3

Pontuação média

90
Ver esta resposta

Votos de vitória

0 / 3

Pontuação média

53
Ver esta resposta

Resultados da avaliação

Modelos avaliadores Google Gemini 2.5 Pro

Motivo do vencedor

A Resposta A é a vencedora clara porque fornece um design significativamente mais robusto, detalhado e correto que se alinha totalmente com as restrições do prompt. A superioridade da Resposta A é mais evidente nos critérios de peso elevado: a sua arquitetura é global e construída para alta disponibilidade, o seu plano de fiabilidade é abrangente (incluindo failover regional crucial) e o seu raciocínio está diretamente ligado aos números fornecidos. Em contraste, a Resposta B comete um erro crítico ao propor uma estratégia de códigos curtos adivinháveis, baseia o seu design numa suposição fraca de região única e está incompleta.

Modelos avaliadores OpenAI GPT-5.5

Motivo do vencedor

A Resposta A vence porque os seus pontos fortes ponderados estão concentrados nos critérios mais importantes: qualidade da arquitetura, completude, raciocínio sobre trade-offs e escalabilidade/confiabilidade. Aborda diretamente todos os requisitos numerados e as restrições declaradas com mecanismos concretos, enquanto a Resposta B falha ou lida fracamente com vários requisitos centrais, especialmente a geração de código não adivinhável, disponibilidade multirregional, planeamento explícito de latência e o design completo de análises.

Modelos avaliadores Anthropic Claude Fable 5

Motivo do vencedor

A vence de forma decisiva nos critérios fortemente ponderados. Na Qualidade da Arquitetura (peso 30) A apresenta um projeto coerente e correto que satisfaz explicitamente a restrição de não ser adivinhável com raciocínio quantificado, enquanto o esquema central de geração de código de B (IDs Snowflake sequenciais codificados em base62, alegadamente não adivinháveis) contradiz o requisito declarado. Na Completude (20) A aborda todos os sete requisitos com números concretos, enquanto B está truncado a meio da frase na secção de análise e nunca aborda o alvo de p99 50 ms com um orçamento de latência. No Raciocínio de Tradeoffs (20) e Escalabilidade/Fiabilidade (20) A nomeia desvantagens reais e fornece failover regional, matemática de margem de capacidade e provisionamento para falhas de cache, enquanto B se mantém mais próximo de um modelo genérico com um design primário de região única. A também supera B em Clareza, apesar da sua extensão. O resultado ponderado favorece fortemente A em todos os critérios.

X f L