O conteúdo deste site foi traduzido usando inteligência artificial (IA) ou tecnologia de tradução automática e pode conter erros.

Skip to content

Como o cache do Roblox sustentou 1,38 bilhão de QPS além dos limites do Redis

Lidando com um aumento de 10 vezes no tráfego com foco na confiabilidade e eficiência

No ambiente de jogos multijogador em grande escala do Roblox, os usuários leem e gravam dados em um volume e velocidade que sobrecarregariam os padrões de cache padrão. Um usuário pode não perceber um atraso de 200 ms em uma página da web padrão que armazena dados estáticos em cache, mas um atraso de 200 ms na recuperação de dados de interação ou metadados do servidor no Roblox poderia interromper o jogo e perturbar o mundo simulado do jogo. O Roblox opera em um ecossistema de dados imprevisíveis, de alta velocidade e efêmeros que devem ser recuperados em milissegundos para preservar a imersão. 

Nossa camada de cache foi projetada para atuar como um enorme amortecedor entre milhões de usuários simultâneos e nosso armazenamento persistente. Ela lida com uma carga de pico de 1,38 bilhão de consultas por segundo (QPS), com clusters lógicos individuais ultrapassando 100 milhões de QPS. Nesta postagem, vamos revelar como arquitetamos um serviço de cache federado para escalar além dos limites dos nós do Redis® e alcançar um throughput massivo, tudo isso enquanto lidamos com um aumento sem precedentes de 10 vezes no tráfego em nosso maior cluster.

Total de leituras/gravações no cache em todos os nós de cache.

Ampliando além dos limites do setor para atender às demandas cada vez maiores

Na Roblox, nosso serviço de cache é construído com base na tecnologia Redis®, e um cluster Redis® tem potencial para suportar até 1.000 nós. No entanto, o limite empírico e aceito pelo setor é muito menor — cerca de 400 a 500 nós.1 Isso se deve ao protocolo Gossip descentralizado do Redis®, que usa comunicação entre nós para compartilhar integridade, status e mapeamento de fragmentos. Em clusters com mais de algumas centenas de nós, o tráfego do protocolo Gossip começa a consumir recursos substanciais de CPU e rede. Cada nó deve processar atualizações de status de um número cada vez maior de pares, desviando recursos da tarefa principal de fornecer dados com baixa latência. Essa sobrecarga do plano de controle pode levar à instabilidade e a um desempenho imprevisível, razão pela qual os provedores de nuvem gerenciada impõem limites de nós. Trata-se de um teto prático que não pode ser ultrapassado sem comprometer a confiabilidade.

Esse limite prático de um único cluster não é suficiente para suportar uma plataforma operando na escala do Roblox, onde o maior serviço de back-end exigiu mais de 100 milhões de QPS de um de nossos clusters lógicos do Redis® no pico, um aumento de 10 milhões em três meses.

Adotamos uma arquitetura federada para superar essa limitação arquitetônica, posicionando um proxy reverso de cliente na frente de vários clusters Redis® menores e independentes. Usamos um limite de 400 nós por cluster para garantir um desempenho previsível. 

Da perspectiva de nossos milhares de aplicativos e serviços, o proxy reverso do cliente apresenta esses clusters distintos como um serviço de cache único, unificado e escalável. Essa federação nos permite escalar horizontalmente quase sem limites, simplesmente adicionando mais clusters à federação, contornando totalmente as restrições do protocolo Gossip. Hoje, nossa maior implantação de cache consiste em mais de 6.000 nós Redis®, que são respaldados por mais de 15 clusters Redis® independentes — uma escala viabilizada apenas por esse modelo federado.

Um diagrama de alto nível da arquitetura federada.

O processo de migração em três etapas

A transição de uma configuração tradicional para uma arquitetura federada, enquanto gerenciávamos centenas de clusters de produção ativos, foi uma tarefa significativa. No final de 2024, muitos desses clusters já estavam se aproximando do nosso limite de 400 nós, tornando urgente a transição para um modelo de maior capacidade. O principal desafio era que as instâncias padrão do Redis® operam isoladamente e não têm consciência inerente de outros clusters, exigindo um método personalizado para replicar dados durante a migração.

Para resolver isso, desenvolvemos um pipeline de migração transparente em três etapas, projetado para fazer a transição dos serviços sem qualquer envolvimento do cliente ou alterações no lado do aplicativo.

O fluxo de trabalho de migração

  1. Gravação dupla: configuramos o proxy reverso do cliente para realizar gravações duplas, enviando os dados recebidos simultaneamente tanto para o cluster original quanto para o novo destino federado.
  2. Paridade e troca de leitura: assim que o processo de gravação dupla preencheu o novo cluster com dados idênticos, como todos os dados são limitados por um tempo de vida (TTL), fizemos a transição do tráfego de leitura do cluster legado para a nova arquitetura federada.
  3. Desativação: Após confirmar a estabilidade do novo cluster, interrompemos todas as operações de gravação no cluster original e o desativamos.

Conseguimos migrar nossos serviços mais críticos para um modelo federado que suporta mais de 6.000 nós, excedendo em muito as limitações de um único cluster Redis®. 

Lidando com o crescimento explosivo do Grow a Garden

A partir de abril de 2025, enfrentamos um desafio de capacidade de uma magnitude que poucos serviços chegam a enfrentar. O catalisador foi o sucesso fenomenal do Grow a Garden. Em apenas algumas semanas após o lançamento, o Grow a Garden começou a quebrar não apenas os recordes da Roblox, mas também os recordes históricos da indústria de jogos em termos de usuários simultâneos (CCU). Em apenas três meses, o público do jogo ultrapassou nosso recorde anterior de CCU para um único jogo, de 2,8 milhões de jogadores, atingindo um pico de mais de 21 milhões. Esse crescimento explosivo enviou 10 vezes mais tráfego para nosso maior cluster Redis® e 3 vezes mais tráfego para o cache geral.

A Roblox opera nossos sistemas de cache em máquinas físicas em nossos próprios data centers, e esse crescimento sem precedentes não fazia parte de nosso plano de capacidade de longo prazo. Para sobreviver a essa onda gigantesca e manter a plataforma estável, tivemos que melhorar radicalmente a eficiência de nossa frota existente, priorizando a confiabilidade. 

Melhorando a eficiência durante o pico

Primeiro, precisávamos identificar os gargalos mais impactantes em nosso sistema para que pudéssemos priorizar o trabalho de otimização. O Roblox Caching é executado em dois pools de hardware diferentes: um para nós de back-end do Redis® e outro para o Envoy. Nossa frota do Redis® é principalmente limitada pela memória, enquanto o proxy do cliente é limitado pela computação. 

Para nossa frota Redis® limitada pela memória, implementamos uma nova política de agendamento para equilibrar melhor a utilização da memória entre nossos grupos de máquinas físicas. Também ajustamos o tamanho do contêiner para reduzir a fragmentação da memória. 

Para melhorar a utilização da CPU, implementamos duas otimizações principais em nosso sistema de cache:

  1. Autoescala do proxy de cliente: ajustamos a política de autoescala para nossa frota de proxies de cliente limitada pela computação. Ao reduzir o desvio permitido em relação à CPU alvo, alcançamos uma maior utilização média da CPU para tarefas sem alterar o limite de escalonamento.
  2. Verificações de integridade do cluster interno: otimizamos as verificações de integridade internas para eliminar heartbeats desnecessários, preservando o intervalo de detecção original e economizando recursos de computação.

Essas mudanças resultaram em uma melhoria de quase 10% na utilização da CPU. Por fim, colocamos essas duas cargas de trabalho muito diferentes no mesmo pool de máquinas com isolamento no nível do contêiner cgroup, o que reduziu nossas necessidades gerais de capacidade em 25%.

Engenharia para confiabilidade inabalável

A confiabilidade continuou sendo nossa principal prioridade, mesmo enquanto corríamos para atender a uma demanda recorde. 

Observabilidade de ponta a ponta

Primeiramente, focamos em compreender possíveis falhas, investindo fortemente em nossa pilha de observabilidade para um monitoramento abrangente e de ponta a ponta da integridade do nosso sistema de cache. Ao rastrear o sucesso do servidor e as falhas do lado do cliente ao longo de todo o ciclo de vida da solicitação, detectamos e diagnosticamos problemas rapidamente, muitas vezes antecipando o impacto no usuário. Por exemplo, adicionamos a detecção de chaves de acesso frequente, que analisa o tráfego em tempo real para identificar dados acessados em excesso e que sobrecarregam a camada de cache. Quando o sistema sinaliza uma chave de acesso frequente, podemos limitar proativamente o tráfego para essas chaves tanto no lado do servidor quanto no lado do cliente, a fim de evitar a sobrecarga do sistema.

Tratamento de falhas

Em qualquer sistema distribuído dessa magnitude, falhas parciais às vezes ocorrem. Projetamos nosso sistema para lidar com essas falhas de maneira elegante e minimizar seu impacto.

  • Falhas parciais em solicitações em lote: reestruturamos o sistema para lidar com falhas parciais em solicitações em lote. Anteriormente, uma única falha de solicitação em um lote fragmentado fazia com que todo o lote falhasse. Agora, as solicitações podem ser bem-sucedidas mesmo que algumas chaves falhem na recuperação.
  • Mitigação do bloqueio de cabeça de fila: espera-se que os sistemas de cache sejam rápidos. Mesmo uma pequena lentidão na rede pode fazer com que as solicitações se acumulem e expiram, um fenômeno conhecido como bloqueio de cabeça de fila. Implementamos mecanismos inteligentes de repetição de tentativas e estratégias de pool de conexões tanto na camada do cliente quanto na camada de proxy para evitar que uma única solicitação lenta afete as outras.
  • Injeção de falhas e latência: Para testar a resiliência, injetamos regularmente falhas controladas (interrupções de nós, interrupções de racks, latência de rede, erros de API) na produção usando nossa estrutura de injeção de falhas. Ao analisar o comportamento do sistema nessas condições, identificamos e corrigimos proativamente os pontos fracos, garantindo confiabilidade contínua.

Resiliência do lado do cliente

Para evitar que nosso sistema de cache seja sobrecarregado por picos repentinos de tráfego, implementamos uma resiliência robusta contra falhas no lado do cliente. Esse mecanismo opera no nível da aplicação, garantindo que nenhum serviço isolado possa monopolizar os recursos do cache.

  • Limitação de taxa para controle de fluxo: nosso cliente possui um limite para o tráfego de saída total, garantindo que ele não envie mais solicitações do que o serviço de back-end pode suportar. As solicitações são limitadas quando esse limite é excedido, o que evita que o serviço seja sobrecarregado.
  • Mecanismos de repetição e tempo limite: nossas bibliotecas de cliente utilizam mecanismos de repetição cuidadosamente ajustados, incluindo tempos limite e um limite de tentativas, para evitar problemas de “thundering herd”. Isso limita o alcance do impacto, libera recursos e melhora a capacidade de resposta geral do sistema, impedindo que travamentos indefinidos e tentativas simultâneas sobrecarreguem o sistema.

O Futuro do Cache do Roblox

A jornada de cache do Roblox começou com clusters Redis® bare-metal gerenciados diretamente por cada proprietário de aplicativo, depois passou para clusters Memcached gerenciados por nossa equipe de cache e, finalmente, fez a transição para um modelo Redis® como serviço, no qual um cluster Redis® é fornecido como um serviço gerenciado. Embora esse modelo tenha se mostrado altamente eficaz em nossa escala atual, reconhecemos suas limitações em termos de eficiência de serviço e isolamento de recursos para uma plataforma tão dinâmica quanto o Roblox.

À medida que a plataforma continua a crescer, planejamos fazer um investimento significativo em um serviço de cache multilocatário de última geração baseado no ValKey. Essa arquitetura foi projetada para reduzir drasticamente os custos por meio do compartilhamento de recursos comuns por meio da multilocação, garantindo ao mesmo tempo o isolamento de dados, recursos e falhas para cada locatário. Nosso objetivo é melhorar significativamente o desempenho, a escalabilidade, a confiabilidade e a eficiência de custo de nossa infraestrutura de cache para atender às demandas de experiências cada vez mais massivas no Roblox.

Agradecimentos: 

Esta conquista foi um esforço colaborativo. Agradecemos aos outros membros da equipe que contribuíram significativamente: Utkarsh Singh, Karthick Ramachandran, Vineesha Kasireddy, Weiji Hu e Leon Gao.

1A AWS limita o ElasticCache a 500 nós.

*Redis é uma marca registrada da Redis Labs Ltd. Todos os direitos sobre a mesma são reservados à Redis Labs Ltd.