Database Sharding (III)

Aunque estas lecciones de escalabilidad en eBay son de carácter general, y a pesar de haber sido escritas en 2008, tienen importantes consejos sobre cómo particionar una base de datos en sharding. Hay varios consejos importantes, y algunos ya los había comentado antes. En esta entrada los repaso.

Primer nivel de particionamiento: por funcionalidad

Pulse en la imagen para acceder al artículo de escalabilidad en eBay

Quizá la primera lección, que se enumera como "Best Practice #1" es que hay que particionar las aplicaciones por funcionalidad. Esta es una práctica que viene siendo ya habitual, y creo que todo el mundo divide las aplicaciones atendiendo a su funcionalidad.

Se menciona también que las aplicaciones deben ser sin estado, como debe ser en sistemas escalables. Obviamente esta recomendación impide seleccionar "frameworks" que promueven la construcción de aplicaciones con estado, como por ejemplo el Seam Framework para JavaEE.

Esta separación funcional de las aplicaciones va acompañada por una separación funcional de las bases de datos también. No hay una única base de datos: tienen un total de mil bases de datos lógicas, instaladas en cuatrocientos servidores físicos (datos del 2008).

Segundo nivel de particionamiento: por tamaño

El segundo nivel de particionamiento aparece en la sección titulada "Best Practice #2: Split Horizontally", en el que se comenta que, por ejemplo, la base de datos de usuarios (una de aquellas primeras mil bases de datos lógicas) se separa en un total de veinte servidores diferentes.

En el artículo se comenta de pasada cómo se realiza esta subdivisión por tamaño. La situación ideal es que este segundo criterio de división permita equilibrar la cantidad de información de cada base de datos (por ejemplo, que de los veinte servidores que comentan todos tengan aproximadamente la misma cantidad de usuarios).

Claves primarias y equilibrio

Una forma sencilla de equilibrar la base de datos lógica de usuarios en esos veinte servidores físicos consiste en asignar un número secuencial a los usuarios (el 1, el 2, etcétera) y luego calcular el resto de dividir este número por el número de "shards", y usar este resto como indicador del 'shard'. Todo esto puede parecer muy complicado, pero es la técnica que usamos cuando repartimos las cartas a los amigos cuando jugamos al mus, por ejemplo.

La técnica es bastante ingenua y presenta dificultades técnicas muy importantes, después de todo es bastante difícil calcular "un número secuencial" cuanto hay veinte bases de datos desparramadas por el centro de datos, ¿no?. Otro día comento sobre qué mecanismos y aplicaciones existen para generar estos "números secuenciales" en un entorno de base de datos particionada.

Resharding

En el artículo se comenta, también de pasada, que de vez en cuando hay que "reparticionar" la base de datos. Por ejemplo, si particionamos la base de datos lógica de usuarios en diez bases de datos físicas podrá ser necesario subdividir estas diez en un total de veinte bases de datos físicas, si la carga así lo requiere. Este procedimiento se conoce como "resharding" y también tiene su miga, y necesita de una entrada de blog futura.

Una recomendación final

Para terminar, el artículo tiene un total de 7 "best practices" explícitas, pero tiene una octava oculta pero muy importante, al final: "scalability is a prerequisite to functionality, a 'priority-0' requirement".

Esto es, hay que pensarse bien si hay que usar sharding o no antes de empezar a pensar siquiera en la funcionalidad. Lo dice un "Distinguished Architect" de eBay, ni más ni menos. Tomemos nota.