El contenido de este sitio se ha traducido mediante inteligencia artificial (IA) o tecnología de traducción automática, y puede contener errores.

Skip to content

Cómo la caché de Roblox mantuvo 1.380 millones de QPS más allá de los límites de Redis

Cómo gestionar un aumento de tráfico de 10 veces con la fiabilidad y la eficiencia en mente

En el entorno de juego multijugador a gran escala de Roblox, los usuarios leen y escriben datos a un volumen y una velocidad que desbordarían los patrones de almacenamiento en caché estándar. Es posible que un usuario no note un retraso de 200 ms en una página web estándar que almacena en caché datos estáticos, pero un retraso de 200 ms en la recuperación de datos de interacción o metadatos del servidor en Roblox podría paralizar el juego e interrumpir el mundo simulado del juego. Roblox opera en un ecosistema de datos impredecibles, de alta velocidad y efímeros que deben recuperarse en milisegundos para preservar la inmersión. 

Nuestra capa de almacenamiento en caché está diseñada para actuar como un enorme amortiguador entre millones de usuarios simultáneos y nuestro almacenamiento persistente. Maneja una carga máxima de 1380 millones de consultas por segundo (QPS), con clústeres lógicos individuales que superan los 100 millones de QPS. En esta publicación, desvelaremos cómo diseñamos un servicio de almacenamiento en caché federado para escalar más allá de los límites de los nodos de Redis® y lograr un rendimiento masivo, todo ello mientras gestionábamos un aumento de tráfico sin precedentes de 10 veces en nuestro clúster más grande.

Total de lecturas/escrituras en caché en todos los nodos de caché.

Ampliando los límites del sector para satisfacer unas demandas en constante crecimiento

En Roblox, nuestro servicio de almacenamiento en caché se basa en la tecnología Redis®, y un clúster de Redis® tiene el potencial de admitir hasta 1000 nodos. Sin embargo, el límite empírico y aceptado por el sector es mucho menor: alrededor de 400-500 nodos.1 Esto se debe al protocolo Gossip descentralizado de Redis®, que utiliza la comunicación entre nodos para compartir información sobre el estado, la salud y la asignación de fragmentos. En clústeres de más de unos pocos cientos de nodos, el tráfico del protocolo Gossip comienza a consumir una cantidad considerable de recursos de CPU y de red. Cada nodo debe procesar actualizaciones de estado de un número cada vez mayor de pares, lo que resta recursos a la tarea principal de servir datos con baja latencia. Esta sobrecarga del plano de control puede provocar inestabilidad y un rendimiento impredecible, razón por la cual los proveedores de nube gestionada imponen límites de nodos. Se trata de un límite práctico que no se puede sobrepasar sin comprometer la fiabilidad.

Este límite práctico de un solo clúster no es suficiente para soportar una plataforma que funciona a la escala de Roblox, donde el servicio de backend más grande exigió más de 100 millones de QPS de uno de nuestros clústeres lógicos de Redis® en horas punta, frente a los 10 millones de hace tres meses.

Adoptamos una arquitectura federada para superar esta limitación arquitectónica, colocando un proxy inverso de cliente delante de múltiples clústeres Redis® más pequeños e independientes. Utilizamos un límite de 400 nodos por clúster para garantizar un rendimiento predecible. 

Desde la perspectiva de nuestras miles de aplicaciones y servicios, el proxy inverso de cliente presenta estos clústeres dispares como un servicio de almacenamiento en caché único, unificado y escalable. Esta federación nos permite escalar horizontalmente casi sin límites simplemente añadiendo más clústeres a la federación, eludiendo por completo las restricciones del protocolo Gossip. En la actualidad, nuestra mayor implementación de almacenamiento en caché consta de más de 6000 nodos Redis®, respaldados por más de 15 clústeres Redis® independientes, una escala que solo es posible gracias a este modelo federado.

Diagrama de alto nivel de la arquitectura federada.

El proceso de migración en tres fases

Pasar de una configuración tradicional a una arquitectura federada mientras se gestionaban cientos de clústeres de producción activos fue una tarea de gran envergadura. A finales de 2024, muchos de estos clústeres ya se acercaban a nuestro límite de 400 nodos, lo que hacía urgente la transición a un modelo de mayor capacidad. El principal reto era que las instancias estándar de Redis® funcionan de forma aislada y no tienen conocimiento inherente de otros clústeres, lo que requería un método personalizado para replicar los datos durante el traslado.

Para resolverlo, desarrollamos un proceso de migración transparente en tres etapas diseñado para realizar la transición de los servicios sin necesidad de que el cliente interviniera ni de realizar cambios en las aplicaciones.

El flujo de trabajo de la migración

  1. Escritura dual: Configuramos el proxy inverso del cliente para realizar escrituras duales, enviando los datos entrantes tanto al clúster original como al nuevo destino federado simultáneamente.
  2. Paridad y cambio de lectura: una vez que el proceso de escritura dual llenó el nuevo clúster con datos idénticos, dado que todos los datos están sujetos a un tiempo de vida (TTL), trasladamos el tráfico de lectura del clúster heredado a la nueva arquitectura federada.
  3. Desactivación: tras confirmar la estabilidad del nuevo clúster, cesamos todas las operaciones de escritura en el clúster original y lo retiramos.

Trasladamos con éxito nuestros servicios más críticos a un modelo federado que admite más de 6000 nodos, superando con creces las limitaciones de un único clúster Redis®. 

Gestión del crecimiento explosivo de Grow a Garden

A partir de abril de 2025, nos enfrentamos a un reto de capacidad de una magnitud que pocos servicios llegan a experimentar. El catalizador fue el éxito fenomenal de Grow a Garden. A las pocas semanas de su lanzamiento, Grow a Garden comenzó a batir no solo los récords de Roblox, sino también los récords históricos de la industria de los videojuegos en cuanto a usuarios simultáneos (CCU). En solo tres meses, la audiencia del juego superó nuestro anterior récord de CCU para un solo juego, de 2,8 millones de jugadores, hasta alcanzar un pico de más de 21 millones. Este crecimiento explosivo envió 10 veces más tráfico a nuestro clúster Redis® más grande y 3 veces más tráfico al almacenamiento en caché general.

Roblox ejecuta nuestros sistemas de almacenamiento en caché en máquinas físicas en nuestros propios centros de datos, y este crecimiento sin precedentes no formaba parte de nuestro plan de capacidad a largo plazo. Para sobrevivir a esta avalancha y mantener la plataforma estable, tuvimos que mejorar radicalmente la eficiencia de nuestro parque de servidores existente, al tiempo que dábamos prioridad a la fiabilidad. 

Mejora de la eficiencia durante el pico

En primer lugar, necesitábamos identificar los cuellos de botella más impactantes de nuestro sistema para poder priorizar el trabajo de optimización. Roblox Caching se ejecuta en dos grupos de hardware diferentes: uno para los nodos backend de Redis® y otro para Envoy. Nuestra flota de Redis® está limitada principalmente por la memoria, mientras que el proxy de cliente está limitado por la capacidad de cálculo. 

Para nuestra flota Redis® limitada por la memoria, implementamos una nueva política de programación para equilibrar mejor la utilización de la memoria entre nuestros grupos de máquinas físicas. También ajustamos el tamaño de los contenedores para reducir la fragmentación de la memoria. 

Para mejorar la utilización de la CPU, implementamos dos optimizaciones clave en nuestro sistema de caché:

  1. Autoescalado del proxy de cliente: ajustamos la política de autoescalado para nuestra flota de proxies de cliente, que depende de la capacidad de cálculo. Al reducir la desviación permitida respecto a la CPU objetivo, logramos una mayor utilización media de la CPU para los trabajos sin cambiar el umbral de escalado.
  2. Comprobaciones de estado del clúster interno: optimizamos las comprobaciones de estado internas para eliminar latidos innecesarios, conservando el intervalo de detección original y ahorrando al mismo tiempo recursos de computación.

Estos cambios dieron lugar a una mejora de casi el 10 % en la utilización de la CPU. Por último, colocamos estas dos cargas de trabajo tan diferentes en el mismo grupo de máquinas con aislamiento a nivel de contenedor cgroup, lo que redujo nuestras necesidades de capacidad global en un 25 %.

Ingeniería para una fiabilidad inquebrantable

La fiabilidad siguió siendo nuestra máxima prioridad, incluso mientras nos apresurábamos a satisfacer una demanda sin precedentes. 

Observabilidad de extremo a extremo

En primer lugar, nos centramos en comprender los posibles fallos invirtiendo fuertemente en nuestra pila de observabilidad para una supervisión integral del estado de nuestro sistema de almacenamiento en caché de extremo a extremo. Al realizar un seguimiento del éxito de los servidores y de los fallos del lado del cliente a lo largo de todo el ciclo de vida de las solicitudes, detectamos y diagnosticamos rápidamente los problemas, a menudo evitando el impacto en los usuarios. Por ejemplo, añadimos la detección de claves calientes, que muestrea el tráfico en tiempo real para identificar datos a los que se accede en exceso y que sobrecargan la capa de almacenamiento en caché. Cuando el sistema señala una clave caliente, podemos limitar de forma proactiva el tráfico hacia estas claves tanto en el lado del servidor como en el del cliente para evitar la sobrecarga del sistema.

Gestión de fallos

En cualquier sistema distribuido de esta envergadura, a veces se producen fallos parciales. Hemos diseñado nuestro sistema para gestionar estos fallos de forma elegante y minimizar su impacto.

  • Fallos parciales en solicitudes por lotes: Hemos rediseñado el sistema para gestionar fallos parciales en solicitudes por lotes. Anteriormente, un solo fallo en una solicitud por lotes fragmentada provocaba el fallo de todo el lote. Ahora las solicitudes pueden completarse con éxito incluso si algunas claves no se pueden recuperar.
  • Mitigación del bloqueo de cola: se espera que los sistemas de almacenamiento en caché sean rápidos. Incluso una ralentización menor de la red puede provocar que las solicitudes se acumulen y agoten el tiempo de espera, un fenómeno conocido como bloqueo de cola. Hemos implementado mecanismos de reintento inteligentes y estrategias de agrupación de conexiones tanto en la capa de cliente como en la de proxy para evitar que una sola solicitud lenta afecte a las demás.
  • Inyección de fallos y latencia: Para probar la resiliencia, inyectamos regularmente fallos controlados (caídas de nodos, caídas de racks, latencia de red, errores de API) en producción utilizando nuestro marco de inyección de fallos. Al analizar el comportamiento del sistema en estas condiciones, identificamos y solucionamos de forma proactiva los puntos débiles, garantizando una fiabilidad continua.

Resiliencia del lado del cliente

Para evitar que nuestro sistema de almacenamiento en caché se vea desbordado por picos repentinos de tráfico, hemos implementado una sólida resiliencia ante fallos del lado del cliente. Este mecanismo opera a nivel de aplicación, garantizando que ningún servicio pueda monopolizar los recursos de la caché.

  • Limitación de velocidad para el control de flujo: nuestro cliente tiene un límite en el tráfico saliente total, lo que garantiza que no envíe más solicitudes de las que el servicio backend puede gestionar. Las solicitudes se limitan cuando se supera este límite, lo que evita que el servicio se vea desbordado.
  • Mecanismos de reintento y tiempo de espera: Nuestras bibliotecas de cliente utilizan mecanismos de reintento cuidadosamente ajustados, que incluyen tiempos de espera y un presupuesto de reintentos, para evitar problemas de «thundering herd». Esto limita el alcance del impacto, libera recursos y mejora la capacidad de respuesta general del sistema al evitar que los bloqueos indefinidos y los reintentos simultáneos saturen el sistema.

El futuro del almacenamiento en caché de Roblox

La trayectoria del almacenamiento en caché de Roblox comenzó con clústeres Redis® bare-metal gestionados directamente por cada propietario de aplicación, pasó luego a clústeres Memcached gestionados por nuestro equipo de almacenamiento en caché y, finalmente, se transformó en un modelo Redis® como servicio, en el que se proporciona un clúster Redis® como servicio gestionado. Aunque este modelo ha demostrado ser muy eficaz a nuestra escala actual, reconocemos sus limitaciones en cuanto a la eficiencia del servicio y el aislamiento de recursos para una plataforma tan dinámica como Roblox.

A medida que la plataforma sigue creciendo, tenemos previsto realizar una inversión significativa en un servicio de almacenamiento en caché multitenant de última generación basado en ValKey. Esta arquitectura está diseñada para reducir drásticamente los costes mediante el uso compartido de recursos comunes a través de la multitenancy, al tiempo que garantiza el aislamiento de datos, recursos y fallos para cada tenant. Nuestro objetivo es mejorar considerablemente el rendimiento, la escalabilidad, la fiabilidad y la rentabilidad de nuestra infraestructura de almacenamiento en caché para satisfacer las demandas de experiencias cada vez más masivas en Roblox.

Agradecimientos: 

Este logro ha sido fruto de un esfuerzo colaborativo. Gracias a los demás miembros del equipo que han contribuido de manera significativa: Utkarsh Singh, Karthick Ramachandran, Vineesha Kasireddy, Weiji Hu y Leon Gao.

1AWS limita ElasticCache a 500 nodos.

*Redis es una marca comercial de Redis Labs Ltd. Todos los derechos sobre la misma están reservados a Redis Labs Ltd.