Escalar la base de datos. Sharding

En los entornos Web 2.0, tenemos básicamente el modelo de embarazadas, donde cada petición es independiente de las otras. Jugamos con la escala, cada petición HTTP en el fondo la podríamos tratar en un servidor diferente y si nuestro servidor HTTP tipo responde en 1 segundo, pues nuestro pico máximo de peticiones por segundo sería el de número de servidores Web/HTTP disponibles.
Hasta aquí todo bien, voy buscando dinero y comprando servidores. Pero es muy raro no tener persistencia, gestión de usuarios, contenidos, etc…, y como tener todos los servidores sincronizados es muy complicado (y más si tenemos UGC (user generated content)), seguramente tendremos en algún lugar una base de datos con nuestros usuarios, perfiles,comentarios,contenidos, todos ellos con muchas modificaciones constantes, recordad UGC… (el causante de todos los males…).

Para seguir con la analogía de las embarazadas, si solo tenemos una base de datos es como si todas quisieran ir al mismo ginecólogo y claro llega un momento que se satura la base de datos (solo puede asistir/visitar a una embarazada en el mismo momento).

Por tanto una opción puede ser tener más instancias de ginecólogo/base de datos y derivar la petición a la base de datos adecuada donde tendremos toda la información que tipicamente pueda necesitar. Esto lo que implica es que habrán muchos datos repetidos de los que tendremos que hacernos cargo a nivel de código, con los que vulneramos parte de las formas normales de las bases de datos, así que mucho cuidado, no rompáis nada.
Este particionado de peticiones a diferentes grupos disjuntos de base de datos se denomina Sharding (o romper en piezas). La principal ventaja que aporta si se hace bien es que volvemos a tener un modelo de escalabilidad casi lineal con los costes. Vas metiendo servidores y vas aguantando la carga.
El gran problema del Sharding es que puede requerir un re-diseño de toda la aplicación, y la mayoría de Start-ups se lo plantean cuando llegan a los limites de su tecnología (2 o 4 sockets en Intel/AMD?) y están perdiendo ingresos (o pérdidas :)) por falta de rendimiento. Y claro son muchas horas de no dormir e introducir bugs y demás…
Así que si te estas planteando desarrollar el siguiente Facebook, Youtube, Flick, Twitter o hasta cierto punto Amazon, considera estos consejos y haz lo que creas oportuno:

  • Empieza desde ya con 2 instancias independientes de servidor HTTP, sea Tomcat, Mongrel, Apache, IIS, JBoss. Así comprobaras todos los problemas que te puede provocar la escalabilidad horizontal en HTTP.
  • Empieza ya con dos instancias (como minimo) de base de datos y accede a ellas con nombres diferentes (mysqlPares.midominio.com y mysqlNones.midominio.com), así cuando excedas la capacidad de 1 servidor los podrás separar con solo un simple cambio de fichero Hosts/DNS.
  • Decide por qué clave quieres romper la base de datos y piensa que las consultas inter base de datos seran muy costosas. Para implementar buscadores, mejor tener una instancia independiente con Lucene, Tokyo Dystopia, htdig, lo que sea, que vaya indexando los contenidos.
  • Todas las consultas a BD deberían incluir la clave para conocer a qué shard está tal o cual dato.
  • Implementa una clase/script por el que te sea fácil mover algo de un shard a otro o subdividir shards.
  • Testear y monitorizar qué pasa cuando algo se cae, en un entorno monolítico si se cae todo el mundo se entera porque afecta al 100%, pero si tenemos 4 BD para el Shard i 10 servidores HTTP puedes afectar al 25% de usuarios y pensar que es culpa de Telefónica…
Y aquí se acaba el post de hoy, que mi fijación por las embarazadas y ginecólogos viene por algo (o algo que viene :)) y me requieren.

Saludos!