Una de las características más interesantes de MongoDB es el sharding. Este concepto, se podría traducir como particionado. Aunque soy firme defensor de usar las palabras en español, creo que la palabra sharding, es más conocida y fácil de identificar en internet.
MongoDB utiliza esta técnica para gestionar la carga de los servidores. Distribuye los datos entre distintos shards (conjuntos de servidores que almacenan parte de los datos), para que la carga a la hora de realizar consultas e inserciones se reparta.
Voy a explicar este concepto con una baraja de cartas. La idea no es mía, es de Kristina Chodorow, autora de varios libros de MongoDB y actualmente trabajando para Google. Yo voy a explicarlo utilizando su idea, pero en español y con una baraja española que es mucho más bonita.
La entrada va a ser solamente teórica. Dejaremos la parte técnica para entradas posteriores.
Punto de partida
Vamos a jugar con una baraja de cartas española de 48 cartas. Para el que no la conozca, decir que esta baraja está dividida en cuatro palos: oros, copas, espadas y bastos. Cada palo tiene doce cartas numeradas del uno al doce.
En la partida jugarán cuatro jugadores, mientras que otra persona será la encargada de repartir las cartas. La persona que reparte las cartas no juega. Solo se dedica a repartir de una forma concreta: repartirá todas las cartas entre los cuatro jugadores, de manera que todos tengan doce cartas como máximo. Eso sí, antes de repartir y decidir a qué jugador le corresponderá la carta, mirará de qué carta se trata. Vamos, que las cartas no son secretas ni deben esconderse.
¿Y en qué se parece este juego al sharding de MongoDB?
Las cartas representarán los documentos a insertar, los jugadores representarán los shards y la persona que reparte se corresponde con el servicio mongos. Este servicio es el que conoce todos los shards, y es el encargado de repartir los documentos a partir de una shard key determinada.
Elegir la clave por la que repartir los documentos (shard key) es una de las decisiones más importantes que tendremos que tomar al usar sharding en MongoDB. Este tema lo trataremos en un artículo más adelante, pero para jugar a nuestro juego de cartas, necesitamos definir una forma de reparto. Para el ejemplo vamos a suponer, que las cartas se repartirán según su valor. Es decir, nos fijaremos en el número que tenga la carta - del uno al doce - y repartiremos en consecuencia.
Empezando el juego
La persona que reparte las cartas coge la primera del mazo y mira su valor. Es el tres de copas. El palo de la carta nos da igual, solo nos fijamos en el valor. Como ninguno de los jugadores tiene cartas, se la da al primer jugador.
Desde el punto de vista de MongoDB, podríamos decir que se se intenta insertar un documento y el proceso mongos decide que como todos los shards están vacíos, debe darle el documento al primero.
Este proceso se repite hasta que el primer jugador va a recibir su doceava carta. Supongamos que la secuencia de las doce cartas ha sido la siguiente: 3,4,9,10,9,2,3,1,12,5,5,6. Si las ordenamos tendríamos algo así como: 1,2,3,3,4,5,5,6,9,9,10,12. Cuando el repartidor va a dar la carta número doce, se da cuenta de que el jugador uno tiene todas, mientras que los demás no tienen ninguna. Entonces se mueven algunas de las cartas del Jugador 1 (incluyendo la carta número doce) al montón del Jugador 2. Para repartir tenemos en cuenta el criterio por el que hemos iniciado el juego, es decir, el valor de la carta. Por tanto el reparto quedará así:
- Jugador 1: 1,2,3,3,4,5,5
- Jugador 2: 6,9,9,10,12
- Jugador 3: sin cartas
- Jugador 4: sin cartas.
El reparto se realiza más o menos por la mitad. Un jugador tendrá las cartas del uno al cinco y el otro del seis al doce. Los números repetidos los tiene que tener el mismo jugador.
Seguimos repartiendo cartas
Ahora hay dos jugadores con cartas (dos shards) que tienen más o menos el mismo número de ellas.
El reparto de cartas continua hasta que uno de los jugadores vuelve a tener doce cartas. En este caso habrá que repartir las cartas también con el jugador número tres. Supongamos que las doce cartas repartidas, y ya ordenadas, han sido las siguientes: 1,4,5,6,7,8,8,9,10,11,11,12.
Importante: por simplicidad estoy repartiendo en bloques de doce cartas, pero las cartas se reparten de una en una y en orden aleatorio. Si un jugador llega a las doce cartas en cualquier momento, habrá que mover cartas de un jugador a otro.
El reparto quedaría de la siguiente manera:
- Jugador 1: 1,1,2,3,3,4,4
- Jugador 2: 5,5,5,6,6,7,8,8
- Jugador 3: 9,9,9,10,10,11,11,12,12
- Jugador 4: sin cartas.
Y vamos a por el penúltimo reparto de cartas, que ya ordenado es: 3,4,5,6,6,7,7,8,9,10,11,12. Y repartido entre los jugadores sería algo así como:
- Jugador 1: 1,1,2,3,3,3
- Jugador 2: 4,4,4,5,5,5,5,6,6,6,6
- Jugador 3: 7,7,7,8,8,8,9,9,9,9
- Jugador 4: 10,10,10,11,11,11,12,12,12
Finalizando el juego
Tras el último reparto de doce cartas, al final las cartas de los jugadores quedarían así:
- Jugador 1: 1,1,1,1,2,2,2,2,3,3,3,3
- Jugador 2: 4,4,4,4,5,5,5,5,6,6,6,6
- Jugador 3: 7,7,7,7,8,8,8,8,9,9,9,9
- Jugador 4: 10,10,10,10,11,11,11,11,12,12,12,12
Un par de cosas a tener en cuenta
El movimiento de documentos entre particiones
Por simplificar, el movimiento de cartas lo he realizado tras repartir doce. Como ya he dicho antes, el movimiento de cartas debería producirse después de que se reparta una y siempre que un jugador tenga doce cartas. Doce cartas es el equivalente al tamaño máximo de un shard.
El tamaño de las particiones
Como número máximo de cartas yo he utilizado doce cartas. Es decir, cada jugador como mucho, podía tener doce cartas. En MongoDB, el tamaño de las particiones no se mide en número de documentos, si no en MB. Por defecto un shard tiene un tamaño máximo de 64 MB, aunque es algo que podemos configurar. Este tamaño está bien para la mayoría de desarrollos, pero puede interesarnos cambiarlo si vemos que los documentos se acumulan en pocos shards o si hay demasiados movimientos de un shard a otro.
Las cartas se acaban, los documentos no
En el ejemplo hemos terminado tras repartir 48 cartas, pero en un escenario real, se continuarían insertando documentos. Si cogiésemos otra baraja, y repartiéramos las cartas otra vez, estas se irían repartiendo por los jugadores. El jugador uno se quedaría con las cartas del uno al tres, el jugador dos con las cartas del cuatro al seis, el tres con las cartas del siete al nueve, y el último jugador se quedaría con las cartas del diez al doce.
Conclusiones
El sharding es una herramienta muy útil para balancear la carga de datos entre servidores. MongoDB nos proporciona una forma sencilla de hacerlo, pero que hay que configurar correctamente. La elección de la clave por la que se realizará el sharding (shard key) es muy importante. Esta elección no se puede cambiar una vez se ha establecido. En el próximo artículo veremos cuál es la mejor manera de elegir una shard key.
Imagen | Guillermo Viciano
Recuerda que puedes ver el índice del tutorial y acceder a todos los artículos de la serie desde aquí.
¿Quiéres que te avisemos cuando se publiquen nuevas entradas en el blog?
Suscríbete por correo electrónico o por RSS