Conflictos

En las bases de datos distribuidas, las copias de datos se pueden almacenar en más de una ubicación. La red natural y las características del sistema de la red pueden indicar que los cambios realizados en un documento almacenado en una ubicación no se puedan actualizar o replicar instantáneamente en otras partes de la base de datos.

Es decir, las actualizaciones independientes se pueden realizar en diferentes copias de documentos. El efecto de estas actualizaciones podría ser la introducción de desacuerdos o "conflictos" en cuanto a cuál es el contenido correcto y definitivo del documento.

IBM® Cloudant® for IBM Cloud® intenta ayudarle a evitar conflictos advirtiéndole de posibles problemas. Te avisa devolviendo una respuesta « 409 » ante una solicitud de actualización problemática. Sin embargo, es posible que no se reciba la respuesta 409 si se solicita la actualización de la base de datos en un sistema que actualmente no está conectado a la red. Por ejemplo, la base de datos puede estar en un dispositivo móvil desconectado temporalmente de Internet, lo que hace imposible comprobar si se han realizado otras actualizaciones potencialmente conflictivas.

Si solicita un documento que está en una situación de conflicto, IBM Cloudant devuelve el documento como se esperaba. Sin embargo, un algoritmo interno tiene en cuenta una serie de factores antes de determinar qué versión de documento se va a devolver. No debe suponer que el documento devuelto es la versión más reciente.

Por ejemplo, si no comprueba los conflictos o no puede abordarlos, la base de datos de IBM Cloudant empezará a mostrar varios comportamientos:

  • Aumento de incoherencias en el contenido del documento, ya que se producen más documentos conflictivos.
  • Aumento del tamaño de la base de datos, ya que todos los documentos conflictivos deben conservarse hasta que se resuelva el conflicto.
  • Disminución del rendimiento, porque IBM Cloudant debe trabajar más como respuesta a cada una de las solicitudes, ya que te intenta identificar la "mejor versión posible" de un documento conflictivo.

Las prácticas siguientes sugeridas pueden ayudarle a decidir cuándo comprobar o resolver conflictos:

Prácticas recomendadas
Característica de aplicación Frecuencia de la actualización de documento ¿Desea comprobar si hay conflictos en la recuperación? ¿Desea comprobar si hay conflictos en la actualización?
Siempre está conectado a la red, por ejemplo, un servidor. A menudo Y
Siempre está conectado a la red. Ocasionalmente
Y
A menudo, aunque no siempre, está conectado a la red, por ejemplo, un portátil. A menudo
Y
A menudo, aunque no siempre, está conectado a la red. Ocasionalmente
Y
A menudo, aunque no siempre, está conectado a la red, por ejemplo, una tableta. A menudo
Y

Búsqueda de conflictos

Para buscar conflictos que puedan afectar a un documento, añada el parámetro de consulta conflicts=true cuando recupere un documento. Cuando se devuelve, el documento resultante incluye una matriz _conflicts, que incluye una lista de todas las revisiones conflictivas.

Consulte la función de correlación de ejemplo siguiente para hallar conflictos en documentos:

function (doc) {
  if (doc._conflicts) {
    emit(null, [doc._rev].concat(doc._conflicts));
  }
}

Para buscar los conflictos correspondientes a varios documentos de una base de datos, escriba una vista. Utilizando una función de correlación como la del ejemplo proporcionado podrá encontrar todas las revisiones para cada documento con un conflicto.

Cuando tenga dicha vista, puede utilizarla para buscar y resolver conflictos según sea necesario. De forma alternativa, puede consultar la vista después de cada réplica para identificar y resolver conflictos inmediatamente.

Cómo resolver conflictos

Después de encontrar un conflicto, puede resolverlo siguiendo los cuatro pasos que se describen a continuación.

  • Obtener
  • Fusionar
  • Subir
  • Suprimir

Consulte el documento de ejemplo siguiente de la primera versión:

{
  "_id": "74b2be56045bed0c8c9d24b939000dbe",
  "_rev": "1-7438df87b632b312c53a08361a7c3299",
  "name": "Samsung Galaxy S4",
  "description": "",
  "price": 650
}

Consideremos un contexto para este ejemplo. Supongamos que tiene una base de datos de productos de una tienda en línea. Es posible que la primera versión de un documento se parezca a la del ejemplo proporcionado.

Consulte la segunda versión siguiente (primera revisión) del documento que añade una descripción:

{
  "_id": "74b2be56045bed0c8c9d24b939000dbe",
  "_rev": "2-61ae00e029d4f5edd2981841243ded13",
  "name": "Samsung Galaxy S4",
  "description": "Latest smartphone from Samsung",
  "price": 650
}

El documento todavía no tiene ninguna descripción, por lo que es posible que alguien la añada.

Consulte la siguiente versión segunda alternativa que introduce un cambio de datos de reducción de precios en la primera versión del documento:

{
  "_id": "74b2be56045bed0c8c9d24b939000dbe",
  "_rev": "2-f796915a291b37254f6df8f6f3389121",
  "name": "Samsung Galaxy S4",
  "description": "",
  "price": 600
}

Paralelamente, otra persona que trabaja con una base de datos replicada reduce el precio. Este cambio se hace en la primera versión del documento. Por lo tanto, el cambio de reducción de precios no conoce el cambio de la descripción.

Más adelante, cuando las dos bases de datos se replican, puede no quedar claro cuál de las dos versiones alternativas del documento es la correcta. Este ejemplo es un contexto de conflicto.

Obtenga las revisiones conflictivas

Para encontrar revisiones conflictivas en un documento, recupere el documento de la forma habitual, pero incluya el parámetro conflicts=true, igual que en el ejemplo siguiente:

https://ACCOUNT.cloudant.com/products/$_ID?conflicts=true

Consulte la respuesta de ejemplo siguiente a la recuperación de documentos que muestra las revisiones conflictivas:

{
  "_id":"74b2be56045bed0c8c9d24b939000dbe",
  "_rev":"2-f796915a291b37254f6df8f6f3389121",
  "name":"Samsung Galaxy S4",
  "description":"",
  "price":600,
  "_conflicts":["2-61ae00e029d4f5edd2981841243ded13"]
}

Si el documento tiene algún conflicto, obtendrá una respuesta similar a la del ejemplo proporcionado, que se basa en la descripción cambiada o el problema de precios modificado.

La versión con el precio cambiado se ha elegido aleatoriamente como la última versión del documento. No suponga que la versión actualizada más reciente del documento es la última versión para fines de resolución de conflictos.

En este ejemplo, se considera que existe un conflicto entre el documento recuperado que tiene el valor _rev 2-f796915a291b37254f6df8f6f3389121, y otro documento que tiene el valor _rev 2-61ae00e029d4f5edd2981841243ded13. Los detalles conflictivos del documento se marcan en la matriz _conflicts.

A menudo, verá que la matriz solo tiene un elemento, pero es posible que existan muchas revisiones conflictivas. Cada revisión se lista en la matriz.

Fusiones los cambios

La aplicación debe identificar todos los cambios potenciales y reconciliarlos, fusionando de manera efectiva las actualizaciones correctas y válidas para producir una única versión no conflictiva del documento.

Para comparar las revisiones e identificar qué ha cambiado, la aplicación debe recuperar todas las versiones de la base de datos. Se empieza recuperando un documento y los detalles de las versiones conflictivas. Para iniciar la recuperación, utilice un mandato similar al siguiente, que también solicita la matriz _conflicts:

https://$ACCOUNT.cloudant.com/products/$_ID?conflicts=true

Esta recuperación le proporciona la versión actual del documento que almacena y una lista del resto de los documentos conflictivos que deben recuperarse, por ejemplo ...rev=2-61ae00e029d4f5edd2981841243ded13 y ...rev=1-7438df87b632b312c53a08361a7c3299. También se recupera y almacena cada una de las otras versiones conflictivas, por ejemplo:

https://$ACCOUNT.cloudant.com/products/$_ID?rev=2-61ae00e029d4f5edd2981841243ded13 https://$ACCOUNT.cloudant.com/products/$_ID?rev=1-7438df87b632b312c53a08361a7c3299

Cuando todas las revisiones conflictivas de un documento estén disponibles, podrá resolver los conflictos.

En un caso de ejemplo anterior, las diferencias entre las versiones del documento correspondían a distintos campos del documento, facilitando así la fusión.

En consecuencia, los conflictos más complejos pueden requerir más análisis. Le recomendamos elegir diversas estrategias de resolución de conflictos distintas, como:

  • En función del tiempo: utiliza una prueba simple de la primera edición o la más reciente.
  • Evaluación del usuario: los conflictos se notifican a los usuarios, que deciden la mejor resolución.
  • Algoritmos de fusión sofisticados: generalmente se utilizan con sistemas de control de versión. Un ejemplo es la fusión de 3 vías.

Para ver un ejemplo práctico sobre cómo implementar los cambios, consulte este proyecto con código de ejemplo.

Cargue la nueva revisión

Consulte las revisiones finales siguientes tras resolver y fusionar los cambios de las versiones anteriores en conflicto:

{
  "_id": "74b2be56045bed0c8c9d24b939000dbe",
  "_rev": "3-daaecd7213301a1ad5493186d6916755",
  "name": "Samsung Galaxy S4",
  "description": "Latest smartphone from Samsung",
  "price": 600
}

Después de evaluar y resolver los conflictos, cree un documento que incluya los datos actuales y definitivos. El nuevo documento se carga a la base de datos.

Suprima las revisiones antiguas

Consulte las siguientes solicitudes de ejemplo para suprimir las versiones antiguas:

DELETE https://$ACCOUNT.cloudant.com/products/$_ID?rev=2-61ae00e029d4f5edd2981841243ded13
DELETE https://$ACCOUNT.cloudant.com/products/$_ID?rev=2-f796915a291b37254f6df8f6f3389121

En el paso final, suprima las revisiones antiguas. Para suprimir las revisiones antiguas, envíe una solicitud DELETE, especificando las revisiones que desea suprimir.

Cuando se suprimen las versiones antiguas de un documento, los conflictos asociados con dicho documento se marcan como resueltos. Puede verificar que no hay conflictos restantes solicitando el documento de nuevo. Establezca el parámetro conflicts en true y utilice buscar conflictos como antes.