Lo primero que debe decidir es una política general sobre qué lado se considera "autorizado" en caso de cambios contradictorios.
Es decir: supongamos que el registro # 125 se cambia en el servidor el 5 de enero a las 10 p.m. y el mismo registro se cambia en uno de los teléfonos (llamémoslo Cliente A) el 5 de enero a las 11 p.m. La última sincronización fue el 3 de enero. Luego, el usuario se vuelve a conectar, digamos, el 8 de enero.
Identificar lo que debe cambiarse es "fácil" en el sentido de que tanto el cliente como el servidor conocen la fecha de la última sincronización, por lo que cualquier cosa creada o actualizada (ver más abajo para más información sobre esto) desde la última sincronización debe reconciliarse.
Entonces, suponga que el único registro modificado es el # 125. O decide que uno de los dos "gana" automáticamente y sobrescribe al otro, o necesita admitir una fase de conciliación en la que un usuario puede decidir qué versión (servidor o cliente) es la correcta, sobrescribiendo la otra.
Esta decisión es sumamente importante y debes ponderar el "rol" de los clientes. Especialmente si hay un conflicto potencial no solo entre el cliente y el servidor, sino en caso de que diferentes clientes puedan cambiar los mismos registros.
[Suponiendo que # 125 puede ser modificado por un segundo cliente (Cliente B), existe la posibilidad de que el Cliente B, que aún no se ha sincronizado, proporcione otra versión del mismo registro, haciendo que la resolución de conflictos anterior sea discutible]
Con respecto al punto " creado o actualizado " anterior ... ¿cómo puede identificar correctamente un registro si se originó en uno de los clientes (asumiendo que esto tiene sentido en el dominio de su problema)? Supongamos que su aplicación administra una lista de contactos comerciales. Si el cliente A dice que tiene que agregar un John Smith recién creado y el servidor tiene un John Smith creado ayer por el cliente D ... ¿crea dos registros porque no puede estar seguro de que no sean personas diferentes? ¿Le pedirá al usuario que también concilie este conflicto?
¿Los clientes tienen "propiedad" de un subconjunto de datos? Es decir, si el Cliente B está configurado para ser la "autoridad" sobre los datos del Área # 5, ¿el Cliente A puede modificar / crear registros para el Área # 5 o no? (Esto facilitaría la resolución de conflictos, pero puede resultar inviable para su situación).
En resumen, los principales problemas son:
- Cómo definir la "identidad" teniendo en cuenta que es posible que los clientes separados no hayan accedido al servidor antes de crear un nuevo registro.
- La situación anterior, sin importar cuán sofisticada sea la solución, puede resultar en la duplicación de datos, por lo que debe prever cómo resolverlos periódicamente y cómo informar a los clientes que lo que ellos consideraron como "Registro # 675" en realidad se ha fusionado o reemplazado por Registro # 543
- Decidir si los conflictos serán resueltos por Fiat (por ejemplo, "La versión de servidor siempre triunfa sobre el cliente de si el primero ha sido actualizado desde la última sincronización") o mediante la intervención manual
- En el caso de fiat , especialmente si decide que el cliente tiene prioridad, también debe ocuparse de cómo tratar con otros clientes aún no sincronizados que pueden tener algunos cambios más en camino.
- Los elementos anteriores no tienen en cuenta la granularidad de sus datos (para simplificar la descripción). Baste decir que en lugar de razonar en el nivel de "Registro", como en mi ejemplo, puede que le resulte más apropiado registrar el cambio en el nivel de campo. O trabajar en un conjunto de registros (por ejemplo, registro de persona + registro de dirección + registro de contactos) a la vez, tratando su agregado como una especie de "meta registro".
Bibliografía:
Más sobre esto, por supuesto, en Wikipedia .
Un algoritmo de sincronización simple del autor de Vdirsyncer
Artículo de OBJC sobre sincronización de datos
SyncML®: Sincronización y administración de sus datos móviles (Reserve en O'Reilly Safari)
Tipos de datos replicados sin conflictos
Replicación optimista YASUSHI SAITO (HP Laboratories) y MARC SHAPIRO (Microsoft Research Ltd.) - Encuestas de computación de ACM, vol. V, No. N, 3 2005.
Alexander Traud, Juergen Nagler-Ihlein, Frank Kargl y Michael Weber. 2008. Sincronización cíclica de datos mediante la reutilización de SyncML. En Actas de la Novena Conferencia Internacional sobre Gestión de Datos Móviles (MDM '08). IEEE Computer Society, Washington, DC, EE. UU., 165-172. DOI = 10.1109 / MDM.2008.10 http://dx.doi.org/10.1109/MDM.2008.10
Lam, F., Lam, N. y Wong, R. 2002. Sincronización eficiente para datos XML móviles. En Actas de la undécima conferencia internacional sobre gestión de la información y el conocimiento (McLean, Virginia, EE.UU., 4 al 9 de noviembre de 2002). CIKM '02. ACM, Nueva York, NY, 153-160. DOI = http://doi.acm.org/10.1145/584792.584820
Cunha, PR y Maibaum, TS 1981. Resource & equil; tipo de datos abstracto + sincronización - Una metodología para la programación orientada a mensajes -. En Actas de la Quinta Conferencia Internacional sobre Ingeniería de Software (San Diego, California, Estados Unidos, 9 al 12 de marzo de 1981). Congreso Internacional de Ingeniería de Software. IEEE Press, Piscataway, Nueva Jersey, 263-272.
(Los últimos tres son de la biblioteca digital de ACM, no tengo idea de si es miembro o si puede obtenerlos a través de otros canales).
Desde el sitio de Dr.Dobbs :
- Creación de aplicaciones con SQL Server CE y SQL RDA por Bill Wagner 19 de mayo de 2004 (Mejores prácticas para diseñar una aplicación tanto para PC de escritorio como para PC móvil - Windows / .NET)
De arxiv.org:
- Un tipo de datos JSON replicado libre de conflictos : el documento describe una implementación de JSON CRDT (los tipos de datos replicados libres de conflictos, CRDT, son una familia de estructuras de datos que admiten modificaciones simultáneas y que garantizan la convergencia de dichas actualizaciones simultáneas).
Recomendaría que tenga una columna de marca de tiempo en cada tabla y cada vez que inserte o actualice, actualice el valor de marca de tiempo de cada fila afectada. Luego, itera sobre todas las tablas verificando si la marca de tiempo es más nueva que la que tiene en la base de datos de destino. Si es más nuevo, verifique si tiene que insertarlo o actualizarlo.
Observación 1: tenga en cuenta las eliminaciones físicas ya que las filas se eliminan de la base de datos de origen y debe hacer lo mismo en la base de datos del servidor. Puede resolver esto evitando eliminaciones físicas o registrando cada eliminación en una tabla con marcas de tiempo. Algo como esto:
DeletedRows = (id, table_name, pk_column, pk_column_value, timestamp)
Entonces, debe leer todas las filas nuevas de la tabla DeletedRows y ejecutar una eliminación en el servidor usando table_name, pk_column y pk_column_value.Observación 2: tenga en cuenta FK ya que la inserción de datos en una tabla relacionada con otra tabla podría fallar. Debe desactivar cada FK antes de la sincronización de datos.
fuente
Si alguien está lidiando con un problema de diseño similar y necesita sincronizar los cambios en varios dispositivos Android, le recomiendo que consulte Google Cloud Messaging para Android (GCM).
Estoy trabajando en una solución en la que los cambios realizados en un cliente deben propagarse a otros clientes. Y acabo de implementar una implementación de prueba de concepto (servidor y cliente) y funciona como un encanto.
Básicamente, cada cliente envía cambios delta al servidor. Por ejemplo, el ID de recurso ABCD1234 ha cambiado del valor 100 a 99.
El servidor valida estos cambios delta contra su base de datos y aprueba el cambio (el cliente está sincronizado) y actualiza su base de datos o rechaza el cambio (el cliente no está sincronizado).
Si el servidor aprueba el cambio, el servidor notifica a otros clientes (excluyendo al que envió el cambio delta) a través de GCM y envía un mensaje de multidifusión con el mismo cambio delta. Los clientes procesan este mensaje y actualizan su base de datos.
¡Lo bueno es que estos cambios se propagan casi instantáneamente! si esos dispositivos están en línea. Y no necesito implementar ningún mecanismo de sondeo en esos clientes.
Tenga en cuenta que si un dispositivo está fuera de línea durante demasiado tiempo y hay más de 100 mensajes esperando en la cola de GCM para su entrega, GCM descartará esos mensajes y enviará un mensaje especial cuando los dispositivos vuelvan a estar en línea. En ese caso, el cliente debe realizar una sincronización completa con el servidor.
Consulte también este tutorial para comenzar con la implementación del cliente CGM.
fuente
esto responde a los desarrolladores que usan el marco de Xamarin (consulte /programming/40156342/sync-online-offline-data )
Una forma muy sencilla de lograr esto con el marco xamarin es utilizar la sincronización de datos sin conexión de Azure, ya que permite enviar y extraer datos del servidor a pedido. Las operaciones de lectura se realizan localmente y las operaciones de escritura se envían a pedido; Si la conexión de red se interrumpe, las operaciones de escritura se ponen en cola hasta que se restablece la conexión y luego se ejecutan.
La implementación es bastante simple:
1) cree una aplicación móvil en Azure Portal (puede probarla gratis aquí https://tryappservice.azure.com/ )
2) conecte su cliente a la aplicación móvil. https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started/
3) el código para configurar su repositorio local:
const string path = "localrepository.db"; //Create our azure mobile app client this.MobileService = new MobileServiceClient("the api address as setup on Mobile app services in azure"); //setup our local sqlite store and initialize a table var repository = new MobileServiceSQLiteStore(path); // initialize a Foo table store.DefineTable<Foo>(); // init repository synchronisation await this.MobileService.SyncContext.InitializeAsync(repository); var fooTable = this.MobileService.GetSyncTable<Foo>();
4) luego presione y extraiga sus datos para asegurarse de que tenemos los últimos cambios:
https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started-offline-data/
fuente
Te sugiero que también eches un vistazo a Symmetricds . es una biblioteca de replicación de SQLite disponible para sistemas Android. puede usarlo para sincronizar la base de datos de su cliente y servidor, también sugiero tener bases de datos separadas en el servidor para cada cliente. Tratar de mantener los datos de todos los usuarios en una base de datos mysql no siempre es la mejor idea. Especialmente si los datos del usuario van a crecer rápidamente.
fuente
Deja llamada que el CUDR sincronización problema (no me gusta CRUD - debido Crear / actualizar / borrar son las escrituras y deben ser emparejados)
El problema también se puede considerar desde la perspectiva de cancelar la línea primero o escribir primero en línea . El enfoque de escritura fuera de línea tiene un problema con el conflicto de identificadores únicos y también múltiples llamadas de red para la misma transacción que aumentan el riesgo (o costo) ...
Personalmente, considero que el enfoque de escribir primero en línea es más fácil de administrar (por lo que será la única fuente de verdad, desde donde se sincroniza todo lo demás). El enfoque de escritura en línea requerirá no permitir que los usuarios escriban fuera de línea primero: escribirán fuera de línea al obtener un formulario de respuesta correcto para escribir en línea.
Primero puede leer sin conexión y, tan pronto como la red esté disponible, obtenga los datos en línea y actualice la base de datos local y luego actualice la interfaz de usuario ...
Una forma de evitar el conflicto de identificador único sería usar una combinación de ID de usuario único + nombre de tabla o ID de tabla + ID de fila (generado por sqlite) ... y luego usar la columna de bandera booleana sincronizada con él ... pero aún así El registro debe realizarse en línea primero para obtener la identificación única en la que se generarán todos los demás identificadores ... aquí el problema también será si los relojes no están sincronizados, lo que alguien mencionó anteriormente ...
fuente