Un sharded cluster es un conjunto de Replica Sets (shards) cuya función es la de repartirse uniformemente la carga de trabajo, de tal manera que nos permite escalar horizontalmente nuestras aplicaciones para así poder trabajar con grandes cantidades de datos. MongoDB uses sharding to support deployments with very large data sets
Ventajas de un sharded cluster
Las principales funcionalidades que nos aporta un sharded cluster son las siguientes:
- Escalabilidad: desde un servidor aislado a arquitecturas distribuidas de grandes clusters (Permite particionar, de manera transparente para el usuario, nuestra base de datos en tantas como shards tengamos. Esto aumenta el rendimiento del procesado de los datos al ser cada una de ellas más pequeña que la original)
- Auto balanceado de carga a través de los distintos shards. El balanceador decide cuándo migrar los datos, y a qué Shard, para que estén uniformemente distribuidos entre todos los servidores del cluster. Cada shard aloja los datos correspondientes a un rango de la clave escogida para particionar nuestra colección.
Configuración de nuestro Sharded Cluster
Esta es la configuración que va a tener nuestro cluster:
- Tres config servers (lo mínimo para producción): su función es la de decirle a los mongos a qué Replica Set, o shard, tienen que enrutar las peticiones de los clientes. Irán en la máquina: juan-mongodbspain
- Dos replica sets (a y b) de tres nodos cada uno (suficiente para mostrar cómo se configura el cluster). Cada Replica Set en una máquina distinta, el primero en: juan-mongodbspain y el segundo en: juan-mongodbspain2.
- Dos mongos (solicitan la información requerida por los clientes al shard que la contiene. Irán en la máquina: juan-mongodbspain
Creación de directorios
Antes de levantar los servicios debemos haber creado los directorios donde guardaremos nuestros datos. Utilizaremos los siguientes:
- cfg0, cfg1 y cfg2 para cada config server
- a0, a1 y a2 para cada uno de los tres nodos de la primera Replica Set
- b0, b1 y b2 para cada uno de los tres nodos de la segunda Replica Set
Orden
Seguiremos este orden para levantar las instancias que componen nuestro sharded cluster:
- Config servers
- mongod’s
- mongo’s
Config servers
Levantamos los config servers:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ mongod --configsvr --port 26050 --logpath /var/lib/mongodb/shardedcluster/log.cfg0 --logappend --dbpath /var/lib/mongodb/shardedcluster/cfg0 --fork about to fork child process, waiting until server is ready for connections. forked process: 5453 child process started successfully, parent exiting juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ mongod --configsvr --port 26051 --logpath /var/lib/mongodb/shardedcluster/log.cfg1 --logappend --dbpath /var/lib/mongodb/shardedcluster/cfg1 --fork about to fork child process, waiting until server is ready for connections. forked process: 5469 child process started successfully, parent exiting juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ mongod --configsvr --port 26052 --logpath /var/lib/mongodb/shardedcluster/log.cfg2 --logappend --dbpath /var/lib/mongodb/shardedcluster/cfg2 --fork about to fork child process, waiting until server is ready for connections. forked process: 5498 child process started successfully, parent exiting juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ |
Mediante la opción ‘configsvr’ indicamos que el servicio va a ser un config server.
Como podemos observar, estamos utilizando la máquina “juan-mongodbspain” para alojar los tres config servers, por esa razón utilizamos puertos distintos. En caso de tenerlos en máquinas distintas no es necesario que especifiquemos ningún puerto.
mongod’s
En un artículo anterior explicamos cómo configurar una Replica Set, podéis leerlo aquí:
Vamos a levantar los servicios correspondientes a los seis nodos. Los tres primeros formarán el primer Replica Set (shard) e irán en una máquina. Los tres últimos formarán el segundo shard e irán en otra máquina.
En el comando que vamos a utilizar hemos de indicar que el mongod va a formar parte de un shard en un cluster particionado. Esto lo conseguimos a través de la opción –shardsvr. El puerto por defecto para estas instancias es el 27018.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ mongod --shardsvr --replSet a --dbpath /var/lib/mongodb/shardedcluster/a0 --logpath /var/lib/mongodb/shardedcluster/log.a0 --port 27000 --fork --logappend --smallfiles --oplogSize 50 about to fork child process, waiting until server is ready for connections. forked process: 5515 child process started successfully, parent exiting juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ mongod --shardsvr --replSet a --dbpath /var/lib/mongodb/shardedcluster/a1 --logpath /var/lib/mongodb/shardedcluster/log.a1 --port 27001 --fork --logappend --smallfiles --oplogSize 50 about to fork child process, waiting until server is ready for connections. forked process: 5562 child process started successfully, parent exiting juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ mongod --shardsvr --replSet a --dbpath /var/lib/mongodb/shardedcluster/a2 --logpath /var/lib/mongodb/shardedcluster/log.a2 --port 27002 --fork --logappend --smallfiles --oplogSize 50 about to fork child process, waiting until server is ready for connections. forked process: 5609 child process started successfully, parent exiting juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ |
Ahora vamos con el segundo Shard, que irá alojado en la otra máquina:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
juan@juan-mongodbspain2:/var/lib/mongodb/shardedcluster$ mongod --shardsvr --replSet b --dbpath /var/lib/mongodb/shardedcluster/b0 --logpath /var/lib/mongodb/shardedcluster/log.b0 --port 27000 --fork --logappend --smallfiles --oplogSize 50 about to fork child process, waiting until server is ready for connections. forked process: 5658 child process started successfully, parent exiting juan@juan-mongodbspain2:/var/lib/mongodb/shardedcluster$ mongod --shardsvr --replSet b --dbpath /var/lib/mongodb/shardedcluster/b1 --logpath /var/lib/mongodb/shardedcluster/log.b1 --port 27001 --fork --logappend --smallfiles --oplogSize 50 about to fork child process, waiting until server is ready for connections. forked process: 5706 child process started successfully, parent exiting juan@juan-mongodbspain2:/var/lib/mongodb/shardedcluster$ mongod --shardsvr --replSet b --dbpath /var/lib/mongodb/shardedcluster/b2 --logpath /var/lib/mongodb/shardedcluster/log.b2 --port 27002 --fork --logappend --smallfiles --oplogSize 50 about to fork child process, waiting until server is ready for connections. forked process: 5754 child process started successfully, parent exiting juan@juan-mongodbspain2:/var/lib/mongodb/shardedcluster$ |
mongo’s
Salvo para tareas de administración nunca nos conectaremos a un mongod ni a un config server. Las apps lo harán a los mongos, que son los encargados de enrutar las peticiones a los shards correspondientes. Es por esta razón por la que estamos especificando puertos distintos al estándar en todas las instancias. Por lo tanto, la única puerta de entrada a la base de datos ha de ser un mongos.
Así se levantan los mongos:
1 2 3 4 5 6 7 8 9 |
juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ mongos --configdb juan-mongodbspain:26050,juan-mongodbspain:26051,juan-mongodbspain:26052 --fork --logappend --logpath /var/lib/mongodb/shardedcluster/log.mongos0 about to fork child process, waiting until server is ready for connections. forked process: 5832 child process started successfully, parent exiting juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ mongos --configdb juan-mongodbspain:26050,juan-mongodbspain:26051,juan-mongodbspain:26052 --fork --logappend --logpath /var/lib/mongodb/shardedcluster/log.mongos1 --port 26061 about to fork child process, waiting until server is ready for connections. forked process: 5894 child process started successfully, parent exiting juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ |
Como vemos, al no haber especificado puerto alguno en el primero de ellos será ese mongos el que utilice el puerto por defecto (27017).
Comprobación de nuestros servicios
Vamos ahora a comprobar que tenemos todas las instancias corriendo:
1 2 3 4 5 6 7 8 9 10 11 |
juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ ps -ef | grep mongo root 5453 2634 0 11:08 ? 00:00:10 mongod --configsvr --port 26050 --logpath /var/lib/mongodb/shardedcluster/log.cfg0 --logappend --dbpath /var/lib/mongodb/shardedcluster/cfg0 --fork root 5469 2634 0 11:08 ? 00:00:10 mongod --configsvr --port 26051 --logpath /var/lib/mongodb/shardedcluster/log.cfg1 --logappend --dbpath /var/lib/mongodb/shardedcluster/cfg1 --fork root 5498 2634 0 11:09 ? 00:00:10 mongod --configsvr --port 26052 --logpath /var/lib/mongodb/shardedcluster/log.cfg2 --logappend --dbpath /var/lib/mongodb/shardedcluster/cfg2 --fork root 5515 2634 0 11:10 ? 00:00:10 mongod --shardsvr --replSet a --dbpath /var/lib/mongodb/shardedcluster/a0 --logpath /var/lib/mongodb/shardedcluster/log.a0 --port 27000 --fork --logappend --smallfiles --oplogSize 50 root 5562 2634 0 11:10 ? 00:00:10 mongod --shardsvr --replSet a --dbpath /var/lib/mongodb/shardedcluster/a1 --logpath /var/lib/mongodb/shardedcluster/log.a1 --port 27001 --fork --logappend --smallfiles --oplogSize 50 root 5609 2634 0 11:11 ? 00:00:09 mongod --shardsvr --replSet a --dbpath /var/lib/mongodb/shardedcluster/a2 --logpath /var/lib/mongodb/shardedcluster/log.a2 --port 27002 --fork --logappend --smallfiles --oplogSize 50 root 5832 2634 0 11:34 ? 00:00:00 mongos --configdb juan-mongodbspain:26050,juan-mongodbspain:26051,juan-mongodbspain:26052 --fork --logappend --logpath /var/lib/mongodb/shardedcluster/log.mongos0 root 5894 2634 0 11:34 ? 00:00:00 mongos --configdb juan-mongodbspain:26050,juan-mongodbspain:26051,juan-mongodbspain:26052 --fork --logappend --logpath /var/lib/mongodb/shardedcluster/log.mongos1 --port 26061 juan 5954 5196 0 11:35 pts/6 00:00:00 grep --color=auto mongo juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ |
Y en la otra máquina tenemos los mongod’s correspondientes al segundo shard:
1 2 3 4 5 |
juan@juan-mongodbspain2:/var/lib/mongodb/shardedcluster$ ps -ef | grep mongo root 5658 2634 0 11:12 ? 00:00:09 mongod --shardsvr --replSet b --dbpath /var/lib/mongodb/shardedcluster/b0 --logpath /var/lib/mongodb/shardedcluster/log.b0 --port 27000 --fork --logappend --smallfiles --oplogSize 50 root 5706 2634 0 11:12 ? 00:00:09 mongod --shardsvr --replSet b --dbpath /var/lib/mongodb/shardedcluster/b1 --logpath /var/lib/mongodb/shardedcluster/log.b1 --port 27001 --fork --logappend --smallfiles --oplogSize 50 root 5754 2634 0 11:12 ? 00:00:09 mongod --shardsvr --replSet b --dbpath /var/lib/mongodb/shardedcluster/b2--logpath /var/lib/mongodb/shardedcluster/log.b2 --port 27002 --fork --logappend --smallfiles --oplogSize 50 juan@juan-mongodbspain2:/var/lib/mongodb/shardedcluster$ |
Configuración de las Replica Set
Ahora tenemos que configurar las dos Replica Set (explicado en el artículo anterior). Sólo muestro cómo se hace para una de ellas porque es idéntico en ambas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
juan@juan-mongodbspain:/var/lib/mongodb/replicaset$ mongo --port 27000 MongoDB shell version: 2.6.6 connecting to: 127.0.0.1:27000/test Hello Juan. Have a good day! > rs.initiate() { "info2" : "no configuration explicitly specified -- making one", "me" : "juan-mongodbspain:27000", "info" : "Config now saved locally. Should come online in about a minute.", "ok" : 1 } a:PRIMARY> rs.add("juan-mongodbspain:27001") { "ok" : 1 } a:PRIMARY> rs.add("juan-mongodbspain:27002") { "ok" : 1 } a:PRIMARY> |
Configuración del cluster
Sólo nos falta añadir al cluster nuestros dos shards. Esto lo haremos desde el primer mongos. Antes de hacerlo podemos comprobar que nuestro cluster no contiene ningún shard:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
juan@juan-mongodbspain:/var/lib/mongodb/shardedcluster$ mongo MongoDB shell version: 2.6.6 connecting to: test Hello Juan. Have a good day! mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "version" : 4, "minCompatibleVersion" : 4, "currentVersion" : 5, "clusterId" : ObjectId("548eb941260fb6e98e17d275") } shards: databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" } mongos> |
Añadimos nuestros dos shards al cluster:
1 2 3 4 5 |
mongos> sh.addShard("a/juan-mongodbspain:27000") { "shardAdded" : "a", "ok" : 1 } mongos> sh.addShard("b/juan-mongodbspain2:27000") { "shardAdded" : "a", "ok" : 1 } mongos> |
Comprobamos la configuración del cluster una vez añadidos los dos shards:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "version" : 4, "minCompatibleVersion" : 4, "currentVersion" : 5, "clusterId" : ObjectId("548eb941260fb6e98e17d275") } shards: { "_id" : "a", "host" : "a/juan-mongodbspain:27000,juan-mongodbspain:27001,juan-mongodbspain:27002" } { "_id" : "b", "host" : "b/juan-mongodbspain2:27000,juan-mongodbspain2:27001,juan-mongodbspain2:27002" } databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" } mongos> |
Balanceador
De esta forma podemos comprobar que está activo el balanceador:
1 2 3 |
mongos> sh.getBalancerState() true mongos> |
Ya hemos terminado de configurar nuestro sharded cluster. Dejamos para otro artículo explicar cómo particionar una colección.
En el próximo artículo hablaremos sobre cómo actualizar un nodo stand-alone, una Replica Set y un Sharded Cluster.
10 ideas sobre “Cómo configurar un Sharded Cluster en MongoDB”
Hola Juan,
soy nuevo en el uso de mongoDB y estoy intentando comprender todo tu artículo (muy interesante por cierto), y tengo algunas dudas..a ver si me puedes echar un cable..
1) Cuando te refieres a mongos, los dos en concreto que pones en el esquema del cluster, a qué te refieres exactamente?
2) Veo que los tres servidores de configuración y los dos mongos van en la misma máquina. Qué pasaría si se cayera esa máquina? Cómo reaccionaría el cluster?
Tengo muchísimas dudas y me gustaría saber si podemos hablar de manera más continuada. no te quitaré mucho tiempo.
gracias y saludos!
Javier Martínez Sáez
Hola Javier!
Cuando hablo de mongos me estoy refiriendo a los routers. Siempre que tenemos un cluster debemos conectar nuestros clientes a MongoDB a través de ellos y, nunca directamente a los nodos de las replicas.
El mongos, gracias a los config servers, sabrá a qué shard debe enrutar las peticiones de los clientes, de tal forma que la configuración del cluster es transparente para ellos.
Con respecto a tu segunda pregunta, la configuración aquí mostrada no es óptima para utilizar en un entorno de producción por el motivo que expones. Sólo intenta comprender cómo configurar el sharded cluster y las posibilidades que MongoDB te permite.
Estoy a tu disposición para todo lo que necesites.
Un saludo
Hola que tal,muy buen aporte! .
Tengo algunas dudas respecto a la configuración del cluster, tal vez me puedas ayudar a comprender mejor esto.
1)Es posible que el cluster funcione con 2 configsvr en producción?
2) Los configsvr deben estar en maquinas diferentes?
3) El Cluster solo funciona con replicas? o es posible su configuración sin ellas?
De ante mano gracias y quedo a la espera de sus aclaraciones u observaciones.
Saludos.
Buenos días Betsabe
Contesto tus preguntas por orden:
1) Es posible que el cluster funcione con 2 configsvr en producción?
Sí es posible, podría funcionar incluso con un único config server. Imagina el caso de un cluster activo y en el que necesitamos realizar alguna labor de administración en los configsvr, como podría ser un upgrade. Mientras dura esa operación el cluster funcionaría con un configsvr menos sin problema.
A pesar de ser posible no es recomendable, ¿por qué? Para garantizar la alta disponibilidad de sus datos. Igual que la configuración mínima recomendada de una Replica Set es de tres nodos.
2) Los configsvr deben estar en maquinas diferentes?
Únicamente por razones de seguridad. MongoDB es totalmente flexible en este sentido. Incluso podrías montar un cluster completo en una única máquina pero, ¿es lógico?, ¿qué pasaría si se cae esa máquina? te quedarías sin servicio ¿verdad? Con los config servers nos pasa igual, si configuramos los tres en una misma máquina y esta se cae…
Siempre has de buscar la mejor configuración posible en función de las máquinas de las que dispongas.
3) El Cluster solo funciona con replicas? o es posible su configuración sin ellas?
El hecho de tener réplicas nos garantiza la alta disponibilidad de los datos. En caso de no preocuparnos esto no es necesario tener réplicas. Por lo tanto, es perfectamente posible un cluster sin réplicas.
En un Replica Set el único nodo que soporta las escrituras y lecturas (por defecto) es el primario, los secundarios, en principio, sólo sirven para recibir la réplica de los datos.
El cluster distribuye la carga de trabajo entre los primarios de sus réplicas de manera uniforme. No necesita la existencia de esos secundarios para su correcto funcionamiento.
Espero haberte servido de ayuda.
Un saludo
Tengo una pregunta tengo actualmente un mongodb y quisiera aligerar la carga de esta a través de Sharded Cluster ya que va empezar a tener mayor carga. Había pensando en agregar 2 servidores mas de mongodb pero por lo que leo necesito 6 mas (uno para cada config de cada maquina y otro para el router), imagino que estas maquinas son mas ligeras en cuanto a hardware cuanto seria lo recomendado?
A decir verdad me gustaría no crear tantos servidores por lo que me planteo que cada router y config vaya en la misma maquina que va fragmentar (osea que tendría 3 servicios relacionados con mongo, cada servidor de mongo correria config, router y shared), seria valida esta arquitectura?
Evidentemente ya tengo datos en el primer servidor de mongo, puedo correr riesgo ?
Hola Mark, ¡gracias por escribir!
Los requerimientos de hardware necesarios para las máquinas que van a correr los servicios de config server son menores que los de aquellas máquinas que van a guardar los datos, los mongod. Es muy dificil darte un consejo sin conocer exáctamente tu aplicación, su modelo de datos, volumen de datos, expectativas de crecimiento, tasas de lectura y escritura, etc.
Lo que sí te puedo decir es que no hay ningún problema «técnico» en que utilices una máquina para correr los mongod, los mongos o, incluso, los config server. Lógicamente, lo ideal sería tener cada uno de ellos en una máquina distinta. Yo crearía los tres config servers desde el principio. En cuanto a los mongos (routers), no es necesario tener uno por cada shard, dependiendo del tráfico que tengas podrás más adelante añadir.
¿Te has planteado implementar una Replica Set en cada shard? Puedes ver cómo hacerlo en este otro artículo How to set up a MongoDB Replica Set
Espero haberte servido de ayuda,
Juan
Hola Juan muchas gracias por responder.
Me ha servido de mucho tu respuesta, voy hacer todo lo posible por separar 3 shared, los 3 config servers y agregar 2(3) mongos (routers), voy a utilizar maquinas mas ligeras para el config y el router (si es posible virtualizadas 1GB de Ram, 1 core y 20GB de HDD), te cuento como me fue.
Me encantaría poder aplicar Replica Set en cada shared, pero no tenemos tanto presupuesto para cada uno 🙁
Mark, no hay ningún problema por tener datos en tu servidor actual. Una vez añadas el resto de shards, habilites el particionado en tu base de datos y particiones tu/tus colección/colecciones el balanceador comenzará a distribuir tus datos entre tus shards para que todos tengan la misma carga de trabajo. Si no lo haces así, tu aplicación seguirá utilizando únicamente el servidor donde reside tu base de datos actual y estarás desaprovechando los nuevos.
Para el particionado de la/las colección/colecciones es muy importante escoger bien la shardkey.
Por favor, cuéntame cómo te ha ido cuando lo tengas en marcha.
Un saludo,
Juan
Buen post!, pero tengo una consulta al agregar un replicaset que se encuentra ubicado en otro servidor: sh.addShard(«b/mongo02:27000»), me sale el siguiente error:
«errmsg» : «could not find host matching read preference { mode: \»primary\» } for set b»,
He revisado, pero no encuentro que podria estar mal, si puedes ayudarme, te lo agracederia.
Saludos
Hola Orwell, ¡muchas gracias por animarte a participar en mi blog!
Lo que está ocurriendo es que no tienes dados de alta en el fichero /etc/hosts, de una o ambas máquinas, los hostnames que estás utilizando.
Gracias de nuevo y un saludo.