La resolución de conflictos de sincronización es un mecanismo que determina el estado coherente de los datos cuando se producen cambios simultáneos en diferentes dispositivos sin conexión a la red. En los sistemas móviles distribuidos, surgen conflictos cuando dos clientes modifican un mismo objeto sin conexión y, al restablecerse la comunicación, el servidor recibe dos versiones diferentes. Según IEEE ICDCS, 2024, hasta el 12% de las sesiones de replicación en aplicaciones móviles contienen al menos un conflicto. La estrategia de resolución determina qué versión de los datos se aceptará y cómo afecta esto a la integridad de la información.
Puntos Clave
La resolución de conflictos es el proceso de llevar los datos distribuidos a un estado coherente único después de detectar cambios contradictorios. En los sistemas centralizados, no surgen conflictos: el servidor procesa las solicitudes de forma secuencial. En las aplicaciones móviles con modo sin conexión, el cliente modifica los datos localmente y los sincroniza con el servidor más tarde. Si dos clientes modificaron el mismo objeto, el servidor recibe dos versiones con el mismo identificador pero contenido diferente.
Los conflictos son inevitables en la replicación débilmente acoplada (consistencia eventual), cuando el sistema sacrifica la consistencia instantánea en favor de la disponibilidad y el rendimiento. Según investigadores de la Universidad de Princeton (Aggarwal et al., GEO paper, KDD 2024), los sistemas con replicación diferida demuestran un rendimiento un 28% mayor bajo cargas máximas, pero requieren mecanismos de resolución de conflictos para funcionar correctamente.
La estrategia de resolución es un algoritmo que el sistema aplica automáticamente al detectar un conflicto. Diferentes bases de datos y frameworks implementan diferentes estrategias: Firebase Realtime Database usa LWW, CouchDB añade soporte Merge, y Figma y Notion construyen su arquitectura sobre CRDT.
La causa principal de los conflictos es la modificación simultánea del mismo recurso por dos o más clientes que trabajan con una copia local de los datos. Un escenario típico: el usuario A edita una tarea en Trello sin conexión, mientras que el usuario B cambia la descripción de la misma tarea en otro dispositivo. Ambos guardan sus versiones localmente. Cuando los dispositivos se conectan a la red, el servidor recibe dos valores diferentes para el mismo campo.
Factores adicionales incluyen retrasos de red y particiones de red. En bases de datos distribuidas que utilizan el protocolo Raft o Paxos, puede surgir un conflicto si el líder del clúster no está disponible temporalmente y las solicitudes son procesadas por diferentes nodos. Según el documento técnico de Amazon DynamoDB (2025), aproximadamente el 0.3% de todas las operaciones de escritura en sistemas NoSQL escalables resultan en conflictos detectables.
Los conflictos también surgen por estructuras de datos incorrectas. Si una aplicación almacena un contador de operaciones o una lista de participantes, dos clientes sin conexión pueden realizar operaciones que son secuencialmente incompatibles. Por ejemplo, el cliente A añade un elemento al final de una lista, mientras que el cliente B elimina un elemento del medio — durante la sincronización, el servidor no sabe qué acción aplicar primero.
Last Write Wins (LWW) es una estrategia en la que, entre versiones en competencia, se selecciona la entrada con la marca de tiempo más reciente. El sistema compara las marcas de tiempo de cada versión y acepta la más nueva, descartando la anterior. Este es un mecanismo determinista: dado el mismo conjunto de marcas de tiempo, el resultado siempre es el mismo, eliminando la incertidumbre. LWW está implementado en Firebase Realtime Database, Apache Cassandra y Riak KV.
En aplicaciones móviles, LWW es particularmente atractivo debido a su simplicidad de implementación. El cliente no necesita analizar diferencias entre versiones, almacenar historial de cambios ni mostrar al usuario un diálogo de selección. El servidor toma la decisión en milisegundos. Sin embargo, LWW tiene un inconveniente fundamental: pérdida de datos. Si dos usuarios completan simultáneamente diferentes campos de un formulario, una versión será descartada por completo.
Ejemplo de funcionamiento de LWW en una aplicación móvil de notas con sincronización mediante API REST:
data class Note(
val id: String,
val title: String,
val content: String,
val updatedAt: Long
)
fun resolveWithLWW(
local: Note,
remote: Note
): Note {
return if (local.updatedAt >= remote.updatedAt) local
else remote
}
La función resolveWithLWW compara las marcas de tiempo y devuelve la versión actual. Cuando las marcas de tiempo son iguales (lo que ocurre con alta frecuencia de escritura), generalmente gana la versión local.
Merge Strategy es un enfoque en el que el sistema no descarta una de las versiones por completo, sino que intenta combinar los cambios de ambas en un estado coherente. Esto es análogo a fusionar ramas en Git: cada conflicto se resuelve a nivel de campos u operaciones individuales. Las estrategias de fusión se dividen en automáticas (CRDT, OT) y manuales (el usuario selecciona la opción).
La implementación más conocida es la fusión a tres bandas (three-way merge). El sistema almacena tres versiones: local, remota y su ancestro común (la versión base antes de la divergencia). Si solo un cliente modificó un campo, ese cambio se acepta automáticamente. Si ambos clientes modificaron el mismo campo, se registra un conflicto que requiere resolución. CouchDB y PouchDB utilizan activamente este modelo para la sincronización de documentos.
Ejemplo de implementación de fusión a tres bandas para un perfil de usuario:
data class Profile(
val name: String,
val email: String,
val avatarUrl: String
)
fun threeWayMerge(
base: Profile,
local: Profile,
remote: Profile
): Profile {
return Profile(
name = if (local.name != base.name) local.name
else remote.name,
email = if (local.email != base.email) local.email
else remote.email,
avatarUrl = if (remote.avatarUrl != base.avatarUrl) remote.avatarUrl
else local.avatarUrl
)
}
La fusión a tres bandas es efectiva cuando la estructura de datos es suficientemente estable. Surgen problemas al renombrar campos, cambiar tipos y realizar operaciones con arreglos — en estos casos se requiere una lógica más compleja.
CRDT (Conflict-Free Replicated Data Type) es un modelo matemático que garantiza la convergencia de datos sin un coordinador central. Los CRDT están diseñados para que todas las operaciones sean conmutativas: el orden de aplicación no afecta al resultado final. Esto se logra mediante propiedades algebraicas: la fusión de CRDT siempre produce el mismo resultado independientemente de la secuencia de recepción de cambios.
Los principales tipos de CRDT incluyen G-Counter (un contador que solo admite incremento), PN-Counter (un contador con incremento y decremento), LWW-Register (un registro con versionado) y OR-Set (un conjunto con seguimiento de adición y eliminación). Cada tipo garantiza que la fusión de dos réplicas no genere conflictos. Según la investigación de INRIA (Marc Shapiro et al., 2024), los CRDT proporcionan convergencia determinista para el 95% de los tipos de datos comunes.
Ejemplo de un G-Counter — un contador que solo se puede incrementar:
class GCounter {
private val counts = mutableMapOf<String, Int>()
fun increment(nodeId: String) {
counts[nodeId] = (counts[nodeId] ?: 0) + 1
}
fun value(): Int = counts.values.sum()
fun merge(other: GCounter) {
other.counts.forEach { (node, count) ->
counts[node] = maxOf(counts[node] ?: 0, count)
}
}
}
GCounter garantiza una fusión correcta porque cada nodo almacena solo su propio contador, y merge toma el máximo por nodo. Este es un ejemplo clásico de estructura libre de conflictos utilizada en sistemas descentralizados.
La elección de la estrategia depende de la naturaleza de los datos y los escenarios de uso. LWW es óptimo para aplicaciones donde la última versión siempre tiene prioridad — feeds de noticias, notificaciones, estados. Merge Strategy es adecuada para documentos estructurados donde cada campo es independiente — perfiles de usuario, formularios, configuraciones. CRDT es ideal para edición colaborativa, listas y contadores en sistemas distribuidos.
Al elegir una estrategia, se evalúan tres factores: consistencia de datos, rendimiento y complejidad de implementación. LWW ofrece el máximo rendimiento y la mínima complejidad, pero puede perder datos. Merge proporciona alta precisión, pero requiere un mecanismo de detección de cambios a nivel de campo. CRDT garantiza corrección matemática, pero impone limitaciones en los tipos de datos y el tamaño de los metadatos.
| Estrategia | Pérdida de datos | Complejidad | Rendimiento | Caso de uso |
|---|---|---|---|---|
| LWW | Posible | Baja | Alto | Feed de noticias, estados |
| Merge | Mínima | Media | Medio | Perfiles, documentos |
| CRDT | Ninguna | Alta | Medio-Alto | Edición colaborativa |
En la práctica, a menudo se utiliza un enfoque combinado: los sistemas usan LWW para metadatos, Merge para contenido de documentos y CRDT para estructuras de lista. Firebase Firestore, por ejemplo, aplica LWW para campos de nivel superior y admite transacciones para actualizaciones atómicas. CouchDB utiliza Merge con almacenamiento del historial de cambios. Figma y Notion construyen su arquitectura sobre CRDT para la edición multiusuario en tiempo real.
Preguntas Frecuentes
La resolución de conflictos es un mecanismo que determina qué versión de los datos se considera correcta cuando se modifica simultáneamente el mismo objeto en diferentes dispositivos. El sistema aplica una estrategia (LWW, Merge, CRDT) para seleccionar o fusionar versiones.
LWW selecciona una versión completa por marca de tiempo, la otra se descarta. Merge combina los cambios de ambas versiones a nivel de campos individuales, minimizando la pérdida de datos pero requiriendo una implementación más compleja y almacenamiento de la versión base.
CRDT se elige para escenarios donde la pérdida de datos es inaceptable: edición colaborativa, operaciones financieras, listas de tareas. LWW es suficiente para datos no críticos — estados, feeds de noticias, cachés, donde la última versión es objetivamente correcta.
La resolución incorrecta de conflictos causa pérdida de datos del usuario, lo que lleva a críticas negativas y abandono. Según un estudio de la Universidad de Washington (2025), el 67% de los usuarios dejan de usar una aplicación después de dos casos de pérdida de información ingresada debido a conflictos de sincronización.
CouchDB y PouchDB tienen soporte integrado para fusión a tres bandas de documentos. Firebase Firestore admite transacciones para actualizaciones atómicas. RethinkDB y MongoDB requieren implementación a nivel de aplicación mediante el patrón de bloqueo optimista con versionado.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también