Fragmentación y replicación

Introducción a la replicación

Lo que se pretende solucionar con la replicación de datos es tener acceso al sistema de información aunque este se caiga, o se produzca una catástrofe, como que se queme el edificio que alberga al servidor. Para conseguir esto se utilizan “replica set”, que son un conjunto de nodos Mongo (mongod), que actúan los unos con los otros como “mirror” en lo que respecta a los datos. Habrá un nodo primario, y el resto de nodos serán secundarios. Los datos se escriben en el nodo primario, y de forma asíncrona se copian los datos a los nodos secundarios. Si el nodo primario se cae, el resto de nodos deciden cuál de ellos pasará a ser el nuevo nodo primario. Cuando el nodo que se había caído, se recupera, vuelve a funcionar como un nodo secundario más. Se necesita un mínimo de tres nodos para formar un “replica set”.

Los tipos de nodos que pueden existir son los siguientes:

  •  El nodo normal → Los que hemos visto hasta ahora, que podrían actuar como nodos primarios o secundarios.
  • El nodo arbitrario → No es un nodo real, y se utiliza para deshacer mayorías en el caso de que el número de nodos sea impar. Por ejemplo, si tienes dos máquinas, es habitual formar los tres nodos del replica set, con dos nodos normales y un nodo que actúe como árbitro
  • Nodo retrasado (delayed) → Se utiliza como nodo de recuperación en caso de desastre. Se puede ajustar para estar con un retraso de un tiempo determinado. Puede participar en las votaciones para seleccionar un nodo primario, pero no puede trabajar como nodo primario (prioridad = 0).
  • Nodo oculto → Se puede utilizar para estadísticas, etc. Y tampoco puede actuar como primario.

En Mongo, por defecto se realizan las lecturas del nodo primario, por lo tanto, si escribimos algo en la base de datos, cuando lo leamos recibiremos una lectura actualizada. Se puede configurar el driver, para efectuar la lectura de los nodos secundarios, lo que nos puede dar lecturas “temporalmente inconsistentes”, es decir, los datos que leemos puede que no estén actualizados, ya que la replicación de datos entre los nodos, se hace de forma asíncrona.

Como se ha comentado, si estamos escribiendo en el nodo primario “nodo a” y este se cae, otro nodo toma el control como primario, por ejemplo el “nodo b”. Cuando vuelve a levantarse el “nodo a” actuará como nodo secundario. El “nodo a” consulta al nodo primario, copia en un archivo sus datos que no fueron replicados por si se quieren recuperar de manera manual y toma los datos del nodo primario, es decir, del “nodo b”. En resumen, el “nodo a” hace “roolback” de los datos que no fueron replicados y algunos datos se perderán. Se puede configurar el driver de mongo, de modo que espere, hasta que los datos se replican a la mayoría de los nodos, de esta manera se minimizan estas pérdidas.

Crear un replica set

Vamos a crear un replica set en nuestro equipo, en este caso lo haremos en Linux. Como no tenemos tres máquinas, lo que vamos a hacer es crear un archivo .sh con este contenido:

Lo que hacemos con esto es crear un directorio en nuestra carpeta de usuario, para seguidamente crear una instancia mongod en el puerto 27017, el conjunto replicaSet se va a llamar “miMongo” y va a dejar el log en la carpeta actual en el archivo “loguno.log”. Con “dbpath”, indicamos el lugar donde queremos almacenar los archivos de base de datos. Creamos del mismo modo, las otras dos instancias de mongod en otros puertos. Guardamos el archivo replicaset.sh y lo ejecutamos en una consola con un comando como el siguiente:

Nota: Si instalamos mongodb en nuestro equipo com un servicio (usando el comando apt-get) tenemos que editar el archivo “/etc/mongodb.conf” y descomentar la linea en la que aparece “ replSet” y hay que dejarla como “replSet = miMongo”

Hecho esto, ya estarán corriendo las tres instancias, pero no hemos indicado cual de ellas está funcionando domo nodo primario. Para ello creamos un archivo llamado config.js, en el que introduciremos lo siguiente:

El id, hace referencia al replica set, los “_ids” que se ponen son arbitrarios y deben ser únicos , y se indican los puertos de cada nodo. En el tercero hemos indicado que no puede ser primario y que los datos no estarán disponibles hasta que pasen 60 segundos. Para lanzar el archivo, nos vamos a conectar al primer nodo de este modo:

Bien, si nos conectamos de esta forma:

Vemos que estamos conectados al nodo primario “miMongo:PRIMARY”, si introducimos:

Se nos mostrará los nodos que hay, y cuales son primarios y secundarios. También podemos usar “rs.isMaster()” para comprobar si somos master o no.

Mongo tiene unas bases de datos locales que almacenan información sobre las operaciones relizadas:

En la colección “oplog.rs” se muestran las operaciones realizadas en la base de datos, que estarán replicadas en todos los nodos. Se puede consultar con “db.oplog.rs.find()”.

Si insertamos unos datos de prueba en el nodo primario y nos conectamos a un nodo secundario para realizar una consulta nos aparecerá el siguiente error:

Para solucionarlo, tenemos que indicar que queremos permitir las lecturas en el nodo secundario:

Otra de las operaciones que podemos realizar es echar abajo un nodo, de este modo:

Fragmentación (Sharding)

La fragmentación es el modo en el que hacemos nuestra base de datos escalable. En lugar de tener una colección en una base de datos, la pondríamos en varias bases de datos distribuidas, de modo que a la hora de consultar los datos de dicha colección, los recuperemos como si de una única base de datos se tratase. Mongo se encargará de averiguar de manera transparente en que base de datos se encuentran los datos.

Los fragmentos, estarán formados por replica set, de modo que si creamos tres fragmentos, cada uno de los cuales tiene un replica set con tres servidores, estaríamos hablando de un total de nueve servidores.

Si hacemos consultas, estas se realizarán de manera distribuida a través de un módulo enrutador llamado “MongoS” que mantendrá un pequeño pull de conexiones a los distintos host. Para conocer en que fragmento debe consultar para recuperar datos de una colección ordenada, se utilizan rangos y shard_key, de modo que se trocea la colección en rangos y les asigna un id (shard_key), que puede ser una parte del propio documento, y se distribuye en los fragmentos (replica set). De modo que cuando se consulte la colección debemos proporcionar el “shard_key”.

De modo que la aplicación ya no se conecta directamente a un replica set, sino que se conectará a “MongoS”

Simular la fragmentación

Se puede simular en nuestro equipo que tenemos varios fragmentos, cada uno formado por un replica set, y de este modo simular el funcionamiento. Los replica set, los crearemos de modo similar a como lo hicimos anteriormente. Por otro lado necesitamos definir un servidor de configuración que realice el seguimiento de donde están los fragmentos. En este caso definiremos tres de forma que estos datos estén también replicados.

Para levantar los servidores abrá que ejecutar en una consola en Linux el siguiente comando:

Donde el archivo simular_fragmentacion.sh va a contener lo siguiente:

Una vez que ejecutamos el comando anterior, si en la consola escribimos “mongo” tenemos lo siguiente:

Como se puede ver nos conectamos al puerto por defecto, www.notodocodigo.com, y en este caso se nos muestra que nos estamos conectando a “mongos”. Si escribimos “sh.status() ” se nos mostrará la información sobre los fragmentos que tenemos, las bases de datos indicando cuales de ellas están fragmentadas y cuales no, así como las “shard key” y los valores que esta puede tomar.

EL desarrollador tiene que tener en cuenta algunas cosas cuando está en un entorno fragmentado:

  • Cada documento debe incluir la “shard key”
  • Esta clave “shard key” es inmutable, una vez que se crea dentro de un documento no se puede cambiar
  • Se necesita un índice que comienza con la “shard key”
  • Cuando se haga un update se debe especificar la “shard key”
  • No se puede tener una clave única a no ser que forme parte de la “shard key”

Bueno, aquí dejamos este artículo, en el siguiente hablaremos sobre el uso de Mongo en Java

2 comentarios:

  1. Hola, buena tarde.

    Tengo un sharding con varias instancias mongod y necesito arrancar estas instancias como servicios al iniciar linux. Había levantado uno con el archivo /etc/rc.local pero al ingresar otra no lo levanta. De casualidad sabes como hacer este proceso?

    • Hola betsabe,

      No puedo darte una respuesta, tendría que mirarlo. No creo que tengas dificultades en encontrar información en Internet sobre cómo ejecutar un script en Linux en el arranque.

      Te recomiendo que mires Mongodb mms https://mms.mongodb.com
      Te permite crear nuevos nodos y escalar horizontalmente desde una aplicación web. De este modo puedes gestionar todo desde un único punto

      Un saludo

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *