sql >> Base de Datos >  >> NoSQL >> MongoDB

Cómo evitar reversiones en MongoDB

La replicación en MongoDB implica conjuntos de réplicas de miembros con una arquitectura de miembros primarios y secundarios, pero a veces con un miembro que no contiene datos llamado árbitro. El proceso de replicación consiste en que, cada vez que los datos se escriben en el nodo principal, los cambios se registran en un archivo oplog desde el cual los miembros secundarios aplican los mismos cambios. Las operaciones de lectura se pueden realizar desde cualquier miembro que contenga datos, por lo que se crea un escenario comúnmente conocido como alta disponibilidad.

Sin embargo, en algunos casos, es posible que los miembros secundarios no se pongan al día con el principal al realizar cambios y, en caso de que el nodo principal falle antes de que se hayan aplicado estos cambios, se verá obligado a resincronizar todo el clúster. para que puedan estar en el mismo estado de datos.

¿Qué es una reversión?

Esta es una función de conmutación por error automática en MongoDB en la que el nodo principal en un conjunto de réplicas puede fallar al realizar cambios que, lamentablemente, terminan sin reflejarse en los miembros secundarios a tiempo desde el registro de operaciones, por lo que es necesario revertir la estado del primario a uno antes de que se hicieran los cambios.

Por lo tanto, las reversiones son necesarias solo cuando el principal ha aceptado escribir las operaciones que no se han replicado en los miembros secundarios antes de que el principal deje de funcionar debido a algún motivo, como una partición de red. Si en caso de que las operaciones de escritura logran replicarse en uno de los miembros que está disponible y accesible para la mayoría del conjunto de réplicas, no se producirá una reversión.

La razón principal detrás de las reversiones en MongoDB es mantener la consistencia de los datos para todos los miembros y, por lo tanto, cuando el principal se reincorpora al conjunto de réplicas, si sus cambios no se han aplicado a los miembros secundarios, se revertirá al estado antes de la falla.

Sin embargo, las reversiones deben ser raras o más bien evitadas en MongoDB, ya que pueden provocar una gran pérdida de datos y, en consecuencia, afectar el funcionamiento de las aplicaciones conectadas a la base de datos.

Proceso de reversión de MongoDB

Consideremos un conjunto de réplicas de tres miembros con A como miembro principal, B y C como miembros secundarios. Completaremos datos en A y, al mismo tiempo, activaremos algunas particiones de red en B y C. Usaremos MongoDB versión 4.2 y Atlas en esta prueba.

Primero obtendremos el estado del conjunto de réplicas ejecutando el comando rs.status() en el shell de mongo  

MongoDB Enterprise Cluster0-shard-0:PRIMARY> rs.status()

Mirando el atributo de los miembros, puede ver algo como

"members" : [

{

"_id" : 0,

"name" : "cluster0-shard-00-00-sc27x.mongodb.net:27017",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",

"uptime" : 1891079,

"optime" : {

"ts" : Timestamp(1594826711, 1),

"t" : NumberLong(27)

},

"optimeDurable" : {

"ts" : Timestamp(1594826711, 1),

"t" : NumberLong(27)

},

"optimeDate" : ISODate("2020-07-15T15:25:11Z"),

"optimeDurableDate" : ISODate("2020-07-15T15:25:11Z"),

"lastHeartbeat" : ISODate("2020-07-15T15:25:19.509Z"),

"lastHeartbeatRecv" : ISODate("2020-07-15T15:25:18.532Z"),

"pingMs" : NumberLong(0),

"lastHeartbeatMessage" : "",

"syncingTo" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",

"syncSourceHost" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",

"syncSourceId" : 2,

"infoMessage" : "",

"configVersion" : 4

},

{

"_id" : 1,

"name" : "cluster0-shard-00-01-sc27x.mongodb.net:27017",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",

"uptime" : 1891055,

"optime" : {

"ts" : Timestamp(1594826711, 1),

"t" : NumberLong(27)

},

"optimeDurable" : {

"ts" : Timestamp(1594826711, 1),

"t" : NumberLong(27)

},

"optimeDate" : ISODate("2020-07-15T15:25:11Z"),

"optimeDurableDate" : ISODate("2020-07-15T15:25:11Z"),

"lastHeartbeat" : ISODate("2020-07-15T15:25:17.914Z"),

"lastHeartbeatRecv" : ISODate("2020-07-15T15:25:19.403Z"),

"pingMs" : NumberLong(0),

"lastHeartbeatMessage" : "",

"syncingTo" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",

"syncSourceHost" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",

"syncSourceId" : 2,

"infoMessage" : "",

"configVersion" : 4

},

{

"_id" : 2,

"name" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",

"health" : 1,

"state" : 1,

"stateStr" : "PRIMARY",

"uptime" : 1891089,

"optime" : {

"ts" : Timestamp(1594826711, 1),

"t" : NumberLong(27)

},

"optimeDate" : ISODate("2020-07-15T15:25:11Z"),

"syncingTo" : "",

"syncSourceHost" : "",

"syncSourceId" : -1,

"infoMessage" : "",

"electionTime" : Timestamp(1592935644, 1),

"electionDate" : ISODate("2020-06-23T18:07:24Z"),

"configVersion" : 4,

"self" : true,

"lastHeartbeatMessage" : ""

}

],

Esto le mostrará el estado de cada miembro de su conjunto de réplicas. Ahora abrimos una nueva terminal para el nodo A y la completamos con 20000 registros:

MongoDB Enterprise Cluster0-shard-0:PRIMARY> for (var y = 20000; y >= 0; y--) {

    db.mytest.insert( { record : y } )

 }

WriteResult({ "nInserted" : 1 })

MongoDB Enterprise Cluster0-shard-0:PRIMARY> db.mytest 2020-07-15T21:28:40.436+2128 I NETWORK  [thread1] trying reconnect to 127.0.0.1:3001 (127.0.0.1) failed

2020-07-15T21:28:41.436+2128 I 

NETWORK  [thread1] reconnect 127.0.0.1:3001 (127.0.0.1) ok

MongoDB Enterprise Cluster0-shard-0:SECONDARY> rs.slaveOk()

MongoDB Enterprise Cluster0-shard-0:SECONDARY> db.mytest.count()

20000

Durante la partición de la red, A estará inactivo, por lo que no estará disponible para B y C y, por lo tanto, B se elegirá como principal en nuestro caso. Cuando A se reincorpora, se agregará como secundario y puede verificarlo usando el comando rs.status(). Sin embargo, algunos registros lograron replicarse en el miembro B antes de la partición de la red, como se ve a continuación:(Recuerde que en este caso B es el principal ahora)

MongoDB Enterprise Cluster0-shard-0:PRIMARY> db.mytest.find({}).count()

12480    

El número es el recuento de documentos que se pudieron replicar en B antes de que A fallara.

Si escribimos algunos datos en B y permitimos que A se una a la red, podemos notar algunos cambios en A

connecting to: 127.0.0.1:3001/admin

MongoDB Enterprise Cluster0-shard-0:ROLLBACK> 

MongoDB Enterprise Cluster0-shard-0:RECOVERING> 

MongoDB Enterprise Cluster0-shard-0:SECONDARY> 

MongoDB Enterprise Cluster0-shard-0:SECONDARY> 

MongoDB Enterprise Cluster0-shard-0:PRIMARY>

Usando un oplogFetcher, los miembros secundarios sincronizan las entradas de oplog desde su syncSource. El oplogFetcher desencadena un método de búsqueda en el registro de operaciones de origen seguido de una serie de series de cursores getMores. Cuando A vuelve a unirse como secundario, se aplica el mismo enfoque y se devuelve un documento mayor que la marca de tiempo del predicado. Si el primer documento en B no coincide con la última entrada de oplog de A, A se verá forzado a retroceder.

Recuperación de datos de reversión en MongoDB

La reversión no es algo malo en MongDB, pero se debe intentar tanto como sea posible para asegurarse de que no suceda muy a menudo. Es una medida automática de seguridad para garantizar la coherencia de los datos entre los miembros de un conjunto de réplicas. En caso de que ocurra una reversión, aquí hay algunos pasos para abordar la situación:

Recuperación de datos de reversión

Debe recopilar datos de miembros con respecto a la reversión. Esto se hace asegurándose de que se creen archivos de reversión (solo disponible con MongoDB versión 4.0) al habilitar createRollbackDataFiles. De forma predeterminada, esta opción se establece en verdadero, por lo que siempre se crearán archivos de reversión.

Los archivos de reversión se colocan en la ruta /rollback/. y contienen datos que se pueden convertir del formato BSON usando la herramienta bsondump a un formato legible por humanos.

Cargar los datos de los archivos de reversión en una base de datos o servidor independiente

Mongorestore es un aspecto vital de MongoDB que puede ayudar a habilitar la recuperación de archivos de datos de reversión. Lo primero es copiar los archivos de reversión en un nuevo servidor y luego usar mongorestore para cargar los archivos en su servidor. El comando mongorestore se muestra a continuación.

mongorestore -u <> -p <> -h 127.0.0.1 -d <rollbackrestoretestdb> -c <rollbackrestoretestc> <path to the .bson file> --authenticationDatabase=<database of user>

Limpieza de datos que no son necesarios y filtrado de datos

Este paso requiere discreción para elegir entre los datos que se conservarán de los archivos de reversión y los datos que se desecharán. Es recomendable importar todos los datos de los archivos de reversión, este punto de decisión hace que este paso sea el paso más difícil en la recuperación de datos.

Uso del Principal como clúster para importar datos 

Comience el paso final descargando los datos limpios mediante el uso de mongorestore y mongodump, luego vuelva a importar los datos en el clúster de producción original.

Prevención de reversiones de MongoDB

Para evitar que ocurran reversiones de datos al usar MongoDB, se puede hacer lo siguiente.

Ejecución de todos los miembros con derecho a voto 'MAJORITY'

Esto se puede hacer usando w:la preocupación de escritura mayoritaria que tiene el poder de opción de solicitud de reconocimiento que permitirá la operación de escritura en etiquetas específicas dadas de instancias de Mongod. Esto se puede lograr usando la opción w seguida de la etiqueta . Para evitar la reversión, todos los miembros con derecho a voto en MongoDB tendrán el diario habilitado y el uso de w:preocupación de escritura mayoritaria, esto garantiza que la mayoría pueda escribir y establecer nodos de réplica antes de que ocurra una reversión. También garantiza que el cliente reciba un reconocimiento después de propagar la operación de escritura en el conjunto de réplicas.

Operaciones de usuario  

Versión actualizada de MongoDB, es decir, la versión 4.2 tiene la capacidad de cerrar todas las operaciones en curso en caso de una reversión.

Compilaciones de índice 

La versión 4.2 de la versión de compatibilidad de características de MongoDB (fcv) "4.2" es capaz de esperar todos los índices en progreso que se están construyendo y terminar todo antes de que se produzca una reversión lugar. Sin embargo, la versión 4.0 espera a que continúe el progreso y crea un índice de fondo, por lo que la posibilidad de una reversión es alta.

Tamaño y limitaciones

La versión 4.0 de MongoDB no tiene límites enumerados de datos dados que se pueden revertir cuando se construye el índice de fondo en curso.

Conclusión 

La reversión de MongoDB es un fenómeno común para aquellos que usan MongoDB sin saber cómo prevenirlo. Las reversiones se pueden prevenir si uno sigue y se adhiere con atención a algunas de las prácticas seguras y formas de evitar reversiones en MongoDB. En general, siempre es recomendable actualizar a la versión más reciente de MongoDB para evitar contratiempos prevenibles.