Tutorial MongoDB. Alta disponibilidad con réplicas

Empezamos una nueva aventura en nuestro tutorial de MongoDB, para meternos de lleno en temas de administración. Y es que, cualquier sistema de base de datos que se precie, debe garantizar al 100 % que sus datos estén disponibles en todo momento. Es lo que se conoce como alta disponibilidad y para conseguirlo MongoDButiliza la replicación.

Nota: esta entrada es teórica. En ella intentaré explicar los conceptos principales de la replicación en MongoDB. En futuras entradas veremos como podemos configurar un conjunto de réplicas.

¿Qué es la replicación?

Básicamente se trata de que los datos estén disponibles en más de un servidor a la vez, para que en el caso de que uno falle por cualquier motivo, los datos se puedan leer o escribir usando otro servidor.

Los servidores de bases de datos tradicionales, llevan a cabo esta tarea organizando los servidores en un clúster, que son, resumiendo mucho,  agrupaciones de servidores que funcionan como un único servidor. Un clúster tradicional puede configurarse con distintos tipos de arquitectura. Cada arquitectura daría para escribir un libro entero, así que no vamos a entrar en muchos más detalles.

MongoDB garantiza la alta disponibilidad de los datos a través de lo que se conoce como conjunto de réplicas. Una réplica no es más que una copia exacta de los datos que estará en otro u otros servidores. Al estar los datos disponibles en varios servidores al mismo tiempo, en el caso de que uno falle, podemos atacar a cualquiera de los otros para recuperar los datos.

En este caso, MongoDBfunciona con un solo servidor principal, considerándose el resto como secundarios. Esto quiere decir que las aplicaciones cliente generalmente se comunican con el servidor principal para leer o escribir datos, y que los cambios se distribuirán a los servidores secundarios para mantener la integridad. Digo en general porque para hacer consultas de solo lectura, podemos acceder también a los servidores secundarios (aunque hay que tener claro que si leemos datos de un servidor secundario, los datos pueden no estar actualizados). Las operaciones de escritura (updates o inserts), solo se pueden hacer sobre el servidor principal.

Componentes de una réplica

Una vez hemos visto de forma general qué es una réplica de MongoDB, vamos a explicar un poco más en detalle los componentes principales.

  • Servidor principal. Es el único servidor de la réplica que acepta operaciones que modifiquen o inserten datos. Cuando recibe un cambio en los datos, el servidor principal lo guarda en un log conocido como oplog.
  • Servidor secundario. En este caso podremos tener más de un servidor secundario. Estos actualizan sus datos a partir del log replicado del servidor principal. Estos servidores se pueden usar para consultar datos, pero nunca para hacer modificaciones directamente sobre ellos.
  • Servidores con prioridad 0. Son servidores que no pueden ser elegidos como principales. Se utilizarán como sustitutos de otro servidor cuando no es fácil añadir nuevos miembros al conjunto de réplicas. Si nuestra base de datos tiene millones de registros, añadir un nuevo miembro al conjunto puede tardar horas, mientras que un servidor con prioridad 0 estará siempre disponible, ya que ya posee los datos replicados.
  • Servidor oculto (hidden). Son servidores que también replican los datos, pero que no pueden ser elegidos como principales (siempre tienen prioridad 0) o utilizados por los clientes para realizar consultas. Para los clientes son invisibles. Se utilizan para tener un servidor dedicado a las copias de seguridad o para tener un servidor para sacar informes. 
  • Servidor retardado (delayed). Son servidores que también replican los datos, pero con un retardo configurado previamente, reflejando un estado anterior del cojunto de datos. Por ejemplo, si lo configuramos con una hora de retraso, este servidor tendrá los datos tal y como estaban una hora antes. Estos servidores se utilizan como protección ante errores humanos que borran colecciones o  ejecutan borrados masivos de forma accidental.
  • Árbitro. Los árbitros no contienen datos y son utilizados para decidir cuál será el nuevo servidor principal en caso de fallo del actual servidor principal. Los árbitros solo se utilizan cuándo tenemos un número par de servidores, con la intención de deshacer el empate ante una elección de servidor principal. Apenas consumen recursos, por lo que se pueden configurar en servidores compartidos.
  • Oplog. El log de operaciones es una colección que almacenan todos los servidores de una réplica. El servidor principal recibe las operaciones de escritura que aplica a sus datos y después guarda en el oplog. Los servidores secundarios copian esta colección de forma asíncrona (del servidor principal o de otro servidor secundario) y aplican también los cambios a sus conjuntos de datos.

Para sincronizar los datos entre servidores de MongoDB, estos se comunican a través de pings o latidos, informando de su estado y de la versión de sus datos. Así los otros servidores son capaces de saber si hay que elegir un nuevo servidor principal, o si sus datos están actualizados.

Elección de un nuevo servidor principal

Lo explicado anteriormente se aplica a un estado estable en el que todos los servidores pueden comunicarse y están funcionando sin problemas. ¿Pero qué pasa cuándo hay algún tipo de fallo en el servidor principal?  Pues en este caso se producirá una elección entre los servidores para elegir cuál será el nuevo servidor principal.

Normalmente un servidor manda pings o latidos a los otros servidores cada 2 segundos. Este latido contiene información sobre el estado de cada servidor y si no es devuelto antes de 10 segundos, el servidor por el que se ha preguntado quedará marcado como inaccesible. Con la información de estos latidos, se decide si es necesario llevar a cabo la elección de un nuevo servidor principal. La elección sucede cuándo:

  • Se está inicializando un nuevo conjunto de réplicas. Es decir, al principio.
  • Un servidor secundario pierde el contacto con el servidor principal. Para que un servidor secundario lance una operación de elección debe tener una prioridad mayor que 0. Ojo, si el servidor secundario es el que se ha quedado aislado (por un corte de red), la elección no tiene por qué llevarse a cabo. Es posible que el resto de servidores estén todavía funcionando y no se necesite elegir un nuevo servidor principal
  • Cuando el servidor principal pasa a ser secundario. Esto que parece raro puede suceder de forma manual (con el comando replSetStepDown), si uno de los secundarios en una elección tiene mayor prioridad o si el servidor principal no puede contactar con la mayoría de servidores secundarios (porque se haya quedado aislado por un corte de red).

En cualquier caso, cuando se lanza una nueva elección, deberemos tener en cuenta los siguientes puntos:

  • Todos los servidores de una réplica tienen un nivel de prioridad que ayuda a elegir el nuevo servidor principal. Esto es útil, por ejemplo,  si queremos configurar réplicas distribuidas geográficamente, de manera que siempre se elija como servidor principal a uno que esté en una ubicación concreta.
  • Cada servidor puede tener asignado un número de votos determinado, que por defecto siempre es de 1. También podemos establecerlo a 0 para que ese servidor no pueda participar en las elecciones. No se debe jugar con los votos para asegurar la elección de un servidor. Para esto es mejor usar la prioridad de los servidores.
  • Solo un servidor que tenga los datos actualizados puede ser elegido como principal. Para saber si está actualizado se utiliza la propiedad optimeque tiene cada servidor, y que guarda una marca de tiempo con la última actualización aplicada
  • Un servidor MongoDBno puede ser elegido como principal si no puede conectar con la mayoría de servidores restantes. Por mayoría se considera al número de votos disponibles en las elecciones, no al número de servidores. Por ejemplo si hay tres servidores con un voto cada uno, y uno de ellos se cae, los otros dos podrán elegir un nuevo servidor principal ya que pueden conectar entre ellos (2 conectan por 1 que no). Si por el contrario se caen dos, el servidor restante no podrá conectar con la mayoría de los servidores (1 conecta, por 2 que no), por lo que permanecerá como secundario o pasará a ser secundario en el caso de que fuera el servidor principal. 
  • Solo tienen derecho a voto los servidores que estén en uno de los estados siguientes PRIMARY, SECONDARY, RECOVERING, ARBITER y ROLLBACK.
  • Todos los miembros de una réplica, incluyendo los que no tienen derecho a voto, pueden vetar a otro servidor que busca ser el principal. Estos vetos pueden producirse si el servidor que busca ser el principal no es miembro del grupo de servidores votantes, si sus datos no están actualizados, si tiene menor prioridad que otro que está disponible, si tiene prioridad 0 o si el servidor principal actual tiene los datos más actualizados (desde la perspectiva del votante)

Como veis el proceso no es sencillo y tiene muchas variantes, por lo que deberemos tener claro como configuramos nuestro conjunto de réplicas para que sea posible elegir siempre un servidor principal. Para esto deberemos tener en mente como es nuestra topología de red y repartir los servidores de forma inteligente. 

Estrategias para configurar los conjuntos de réplicas

Siempre que vayamos a crear un nuevo conjunto de réplicas en nuestra base de datos MongoDB deberemos tomar una serie de decisiones importantes.

Cuando tengamos que decidir cuántos miembros tendrá nuestro conjunto de réplicas o cuándo añadir nuevos miembros, deberemos pensar en los siguientes puntos:

  • Siempre hay que intentar añadir un número impar de servidores al conjunto para garantizar la elección de un nuevo servidor principal en caso de fallo. Si el número es par, es recomendable que añadamos algún árbitro.
  • Tenemos quetener en cuenta la tolerancia a fallos, es decir, cuántos servidores pueden fallar sin que suframos problemas para elegir un nuevo servidor principal. La tolerancia se calcula restando al número de servidores disponibles, el número de votos necesarios para conseguir la mayoría en el caso de elección de un nuevo servidor. Si tenemos 3 servidores se necesitarán 2 votos, por lo que la tolerancia es de 1. Si tenemos 4 servidores se necesitarán 3 votos para la mayoría, por lo que la tolerancia también es de 1. Si tenemos 6 servidores, se necesitarán 4 votos, por lo que la tolerancia en este caso será de 2. Como veis añadir un nuevo miembro al conjunto no siempre aumentará la tolerancia a fallos.
  • Podemos utilizar servidores ocultos o retardados para funciones específicas.
  • Si se realizan muchísimas operaciones de consulta, podemos repartir el tráfico entre los servidores secundarios, para distribuir la carga.
  • Hay que añadir nuevos miembros al conjunto antes de que sea tarde. Si la capacidad del conjunto de réplicas actual está empezando a ser insuficiente, añade un nuevo miembro. Hazlo con antelación y no esperes a que la capacidad sea sobrepasada.

También tendremos que pensar en la distribución de los servidores:

  • Es mejor distribuir los servidores geográficamente. Si un servidor falla, es recomendable que esos datos estén disponibles en otra red diferente.
  • Es mejor tener la mayoría de los servidores en una sola localización. En el caso de una nueva elección de servidor principal, es necesaria una mayoría de votos, por lo que habrá que asegurarse que en caso de que las comunicaciones fallen, la mayoría de servidores esté disponible en una sola localización. Si no es así, no podremos elegir un nuevo servidor principal.
  • Y por último, es aconsejable utilizar journaling, para proteger la integridad de nuestros datos en caso de un apagado inesperado del servidor (fallos de energía, reinicios inesperados, fallos de hardware etc.). Con journalinglo que hacemos es que MongoDBprimero guarde las operaciones que va a realizar en un archivo del disco duro antes de aplicarlas. Si se produce un apagado inesperado, MongoDBpodrá restaurar el estado de la base de datos a un estado consistente. 

Conclusiones

Con la replicaciónMongoDB asegura que nuestros datos estén siempre accesibles. No obstante la configuración de un conjunto de réplicas no es algo trivial, y debe hacerse a partir de un estudio previo analizando qué queremos conseguir. A partir de ahí podremos tomar decisiones y decidir cómo podemos llevar a buen puerto nuestro sistema de alta diponibilidad, ya que las variables que influyen en el sistema son muchas. En futuras entregas veremos como podemos configurar un conjunto de réplicas y los diferentes casos que nos podremos encontrar. No os lo perdáis.



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