Searching...
jueves, 12 de enero de 2017

Introducción a la Replicación en MongoDB


Utilizar un servidor independiente, un servidor mongod único, es una manera fácil de empezar, pero una forma peligrosa de funcionar en producción: ¿Y si el servidor se bloquea o deja de estar disponible? La base de datos no estará disponible al menos por un tiempo. Si hay problemas con el hardware, puede que tengamos que mover los datos a otra máquina. En el peor de los casos, los problemas con el disco o con la red podrían dejarnos con datos corruptos o inaccesibles.

La replicación es una forma de mantener copias idénticas de los datos en varios servidores y se recomienda para todas las implementaciones de producción. La replicación mantiene la aplicación funcionando y nuestros datos seguros, incluso si algo le sucede a uno o más de los servidores.
Replicación en MongoDB

Con MongoDB, configuramos la replicación creando un conjunto de réplica. Un conjunto de réplica es un grupo de servidores con un primario, el servidor atendiendo las solicitudes del cliente y múltiples secundarios, servidores que guardan copias de los datos del primario. Si el primario sufre algún daño, los secundarios pueden elegir a un nuevo primario de entre ellos.

Si estamos utilizando la replicación y un servidor se cae, todavía se puede acceder a los datos de los otros servidores del conjunto. Si los datos de un servidor están dañados o inaccesibles, se puede hacer una nueva copia de los datos desde otro de los miembros del conjunto. 

Una Configuración de Conjunto de Réplica de Prueba en 1 Minuto. 

Esta sección te ayudará a comenzar rápidamente configurando un conjunto de réplica de tres miembros en tu máquina local. Obviamente esta configuración no es adecuada para producción, pero es una buena manera de familiarizarse con la replicación y jugar con la configuración.


Este método de inicio rápido almacena los datos en /data/db, así que asegúrate de que el directorio existe y que tu usuario pueda escribirlo antes de ejecutar este código.


Inicia un shell de mongo con la opción --nodb, que te permite iniciar un shell que no esté conectado a ningún mongod:

$ mongo --nodb

Crea un conjunto de replica ejecutando el siguiente comando:

> replicaSet = new ReplSetTest({"nodes" : 3})

Esto le dice al shell que cree un nuevo conjunto de réplica con tres servidores: uno principal y dos secundarios. Sin embargo, en realidad no inicia los servidores mongod hasta que ejecutes los dos comandos siguientes:

> // Inicia los tres procesos mongod
> replicaSet.startSet()
> 
> // configura la replicación
> replicaSet.initiate()

Ahora deberías tener tres procesos mongod ejecutándose localmente en los puertos 31000, 31001 y 31002. Todos ellos estarán volcando sus logs en el shell actual, lo que es muy ruidoso, así que deja este shell a un lado y abre uno nuevo.


En el segundo shell, conéctate al mongodb que se ejecuta en el puerto 31000:

> conn1 = new Mongo("localhost:31000")
connection to localhost:31000
testReplSet:PRIMARY>
testReplSet:PRIMARY> primaryDB = conn1.getDB("test")
test

Observa que, cuando te conectas a un miembro de conjunto de réplica, el indicador cambia a testReplSet:PRIMARY>. "PRIMARY" es el estado del miembro y "testReplSet" es un identificador para este conjunto. Aprenderás a elegir tu propio identificador más tarde; TestReplSet es el nombre predeterminado que ReplSetTest utiliza.

Por legibilidad, los ejemplos de ahora en adelante simplemente usarán el símbolo > para el indicador de entrada en lugar de testReplSet:PRIMARY>.

Utiliza tu conexión al primario para ejecutar el comando isMaster. Esto te mostrará el estado del conjunto:

> primaryDB.isMaster()
{
"setName" : "testReplSet",
"ismaster" : true,
"secondary" : false,
"hosts" : [
"wooster:31000",
"wooster:31002",
"wooster:31001"
],
"primary" : "wooster:31000",
"me" : "wooster:31000",
"maxBsonObjectSize" : 16777216,
"localTime" : ISODate("2012-09-28T15:48:11.025Z"),
"ok" : 1
}

Hay un montón de campos en la salida de isMaster, pero los más importantes indican que se puede ver que este nodo es primario (el campo "ismaster":true) y que hay una lista de hosts en el conjunto.


Si este servidor dice "ismaster":false, está bien. Observa el campo "primary" para ver qué nodo es primario y luego repite los pasos de conexión anteriores para ese host / puerto.


Ahora que estás conectado al primario, vamos a intentar hacer algunas escrituras y veamos qué sucede. Primero, inserta 1.000 documentos:

> for (i=0; i<1000; i++) { primaryDB.coll.insert({count: i}) }
> 
> // nos aseguramos que están los documentos
> primaryDB.coll.count()
1000
Ahora comprueba uno de los secundarios y verifica que tengan una copia de todos estos documentos. Conéctate a cualquiera de los secundarios:

> conn2 = new Mongo("localhost:31001")
connection to localhost:31001
> secondaryDB = conn2.getDB("test")
test

Los secundarios pueden retrasarse con respecto al primario y no tener las escrituras más actuales, por lo que los secundarios rechazarán las solicitudes de lectura por defecto para evitar que las aplicaciones lean accidentalmente datos obsoletos. Por lo tanto, si intentas consultar un secundario, obtendrás un error indicando que no es primario:

> secondaryDB.coll.find()
error: { "$err" : "not master and slaveok=false", "code" : 13435 }

Esto se hace para proteger la aplicación de conectarse accidentalmente a un secundario y leer datos obsoletos. Para permitir consultas en el secundario, establecemos un indicador "Estoy bien con la lectura de secundarios", del siguiente modo:

> conn2.setSlaveOk()

Observa que slaveOk se establece en la conexión (conn2), no en la base de datos (secondaryDB).
Ahora ya estás listo para leer de este miembro. Ejecuta la consulta como de costumbre:

> secondaryDB.coll.find()

{ "_id" : ObjectId("5037cac65f3257931833902b"), "count" : 0 }
{ "_id" : ObjectId("5037cac65f3257931833902c"), "count" : 1 }
{ "_id" : ObjectId("5037cac65f3257931833902d"), "count" : 2 }
...
{ "_id" : ObjectId("5037cac65f3257931833903c"), "count" : 17 }
{ "_id" : ObjectId("5037cac65f3257931833903d"), "count" : 18 }
{ "_id" : ObjectId("5037cac65f3257931833903e"), "count" : 19 }
Type "it" for more
> 
> secondaryDB.coll.count()
1000

Se puede ver que todos los documentos están ahí.

Ahora, intenta escribir a un secundario:

> secondaryDB.coll.insert({"count" : 1001})
> secondaryDB.runCommand({"getLastError" : 1})
{
"err" : "not master",
"code" : 10058,
"n" : 0,
"lastOp" : Timestamp(0, 0),
"connectionId" : 5,
"ok" : 1
}

Puedes ver que el secundario no acepta la escritura. El secundario realizará solamente las escrituras que consiga a través de la replicación, no procedente de clientes.

Hay otra característica interesante que debes probar: la recuperación automática. Si el primario se cae, uno de los secundarios será elegido primario de forma automática. Para probar esto, para el primario:

> primaryDB.adminCommand({"shutdown" : 1})

Ejecutar isMaster en el secundario para ver quién se ha convertido en el nuevo primario:

> secondaryDB.isMaster()

Debe ser algo como esto:

{
"setName" : "testReplSet",
"ismaster" : true,
"secondary" : false,
"hosts" : [
"wooster:31001",
"wooster:31000",
"wooster:31002"
],
"primary" : "wooster:31001",
"me" : "wooster:31001",
"maxBsonObjectSize" : 16777216,
"localTime" : ISODate("2012-09-28T16:52:07.975Z"),
"ok" : 1
}

Nuestro principal puede ser el otro servidor; Cualquiera de los secundarios que se diera cuenta primero que el primario estaba caído será elegido. Ahora puedes enviar escrituras al nuevo primario.

IsMaster es un comando muy antiguo, precediendo a los conjuntos de réplicas, cuando MongoDB sólo soportaba la replicación maestro-esclavo. Por lo tanto, no utiliza la terminología de conjunto de réplica de forma coherente: todavía llama al primario un "maestro". Generalmente se puede pensar en "maestro" como equivalente a "primario" y "esclavo" como equivalente a "secundario".

Cuando hayas terminado de trabajar con el conjunto, para los servidores del primer shell. Este shell estará lleno de salida de los logs de los miembros del conjunto, así que presiona Enter varias veces para volver a un indicador de entrada (prompt). Para apagar el conjunto, ejecuta:
> replicaSet.stopSet()

¡Enhorabuena! Acabas de configurar, utilizar y desmantelar la replicación.

Hay algunos conceptos clave a tener en cuenta:
  • Los clientes pueden enviar a un primario todas las mismas operaciones que podrían enviar a un servidor autónomo (lecturas, escrituras, comandos, compilaciones de índices, etc.). 
  • Los clientes no pueden escribir en secundarios. 
  • Los clientes, por defecto, no pueden leer de secundarios. Al establecer explícitamente una configuración del tipo "Sé que estoy leyendo de un secundario", los clientes podrán leer de secundarios.

0 comentarios:

Publicar un comentario

Gracias por participar en esta página.

 
Back to top!