Post invitado: Tom Rosenfeld, Jefe de equipo, Come2Play
Come2Play es una empresa que sirve juegos web multijugador en línea. Nuestro sitio sirve a más de 4 millones de jugadores al mes, con decenas de miles de jugadores en un momento dado. Utilizamos MySQL como base de datos e IIS en nuestros servidores web, que ejecutan ASP.Net y asp clásico (código heredado).
Como aplicación web a gran escala, nos dimos cuenta de que necesitábamos poder escalar. Una de las formas más sensatas y comunes de ayudar al escalado en la arquitectura web actual es utilizar una capa de almacenamiento en caché, y el software más utilizado para ello es, obviamente, Memcached.
Cuando busqué una librería Memcached para ASP.Net encontré el Enyim Memcached Client, que me llevó a Membase (entonces llamado NorthScale). Tras experimentar un poco con la versión "normal" de Memcached y compararla con Membase, varias ventajas inmediatas quedaron muy claras:
- Separación de cubos
- Configuración muy sencilla
- Facilidad de instalación
- Una consola de gestión de interfaz web muy pulida e intuitiva
- Una forma segura de utilizar Memcached y Membase en la misma implementación
En cuanto a la configuración:
En lugar de tener que gestionar una lista de todos nuestros servidores Memcached en un archivo de configuración, me limité a definir un único punto de entrada a un servidor Membase. Instalé Membase en nuestros servidores IIS y dejé que localhost fuera el punto de entrada, esquivando así la temida bala del fallo de punto único y manteniendo nuestros archivos de configuración sucintos.
Optamos por asimilar el uso de Memcached y Membase de forma muy gradual, para evitar riesgos y no estrangular el desarrollo de nuevas funcionalidades (un punto de vista muy ágil).
Nuestro proyecto consta de tres fases principales:
- Fase 1: Almacenamiento en caché de consultas pesadas en un cubo Memcached dedicado
- Fase 2: Almacenamiento en caché de datos específicos del usuario en un bucket Memcached específico del usuario.
- Fase 3: Guardar los datos específicos del usuario en un bucket de Membase
Fase 1: Consultas pesadas
El reto preliminar era crear una biblioteca apta tanto para .Net como para COM. Una vez que nos ocupamos de nuestra biblioteca, el resto fue fácil. El efecto en nuestros servidores MySQL fue muy positivo y notable: una reducción significativa de las tablas temporales significó más memoria libre para los índices y una mejora masiva del rendimiento general del sitio, por no mencionar la esperada reducción de las consultas/segundo.
Con la implementación básica de Memcached, pude implementar la primera fase rápidamente usando la consulta con sus parámetros añadidos como claves en Memcached y escribiendo un método llamado "GetDataTableCached", que coge los datos de la caché o de la base de datos en caso de fallo y los almacena en caché. Luego, recorriendo todas las llamadas a "GetDataTable" pude encontrar y reemplazar todas las llamadas que no eran específicas del usuario con "GetDataTableCached".
Establezco un tiempo de espera de 15 minutos en estas claves para que los datos de la caché no se vuelvan demasiado obsoletos. De este modo, si alguien cambia una configuración del sistema a través de nuestro sistema CMS, ésta tendrá efecto en 15 minutos como máximo. La ventaja de este enfoque es obvia: no hay necesidad de escribir código para invalidar o actualizar estas claves.
También tenga en cuenta que el almacenamiento en caché de un resultado de los métodos podría ser aún más simple con el uso de AOP (por ejemplo, PostSharp). He optado por evitar que debido al aumento de los tiempos de construcción.
Fase 2: Datos específicos del usuario
Este movimiento es muy gradual, ya que estamos moviendo datos que son:
- En uso muy alto - comprobamos los logs de MySQL para encontrar estos
- Fácil de mover: datos que se modifican desde muchos lugares del código.
(por ejemplo, la moneda virtual del usuario) es mucho más difícil de mover que los datos que nunca
cambios (por ejemplo, la fecha de registro del usuario)
Fase 3: Datos específicos del usuario con persistencia en disco
Este paso fue muy fácil después de las fases anteriores gracias a una solución muy simple y elegante (y por cierto lo que creo que es el principal punto fuerte de Membase) - utiliza exactamente el mismo protocolo "on the wire" utilizado por Memcached. Esto es útil para dos cosas:
- Trasladar los datos relevantes de MySQL a Membase
- Utilizar Membase para las nuevas funciones y prescindir por completo de MySQL
En resumen, Membase permite a Come2Play ampliarse fácilmente. Nos encanta Membase porque es fácil de usar, elegante y pulido.