web-dev-qa-db-fra.com

Synchroniser les bases de données client-serveur

Je recherche des stratégies générales pour la synchronisation des données sur un serveur central avec des applications clientes qui ne sont pas toujours en ligne.

Dans mon cas particulier, j’ai une application pour téléphone Android avec une base de données sqlite et une application Web PHP avec une base de données MySQL. 

Les utilisateurs pourront ajouter et modifier des informations sur l'application du téléphone et sur l'application Web. Je dois m'assurer que les modifications apportées à un endroit sont répercutées partout, même lorsque le téléphone ne peut pas communiquer immédiatement avec le serveur.

Je ne suis pas préoccupé par la façon de transférer des données du téléphone au serveur ou inversement. Je mentionne mes technologies particulières uniquement parce que je ne peux pas utiliser, par exemple, les fonctionnalités de réplication disponibles pour MySQL.

Je sais que le problème de synchronisation des données client-serveur existe depuis très longtemps et je voudrais des informations - articles, livres, conseils, etc. - sur les modèles de traitement du problème. J'aimerais connaître les stratégies générales de gestion de la synchronisation pour comparer les forces, les faiblesses et les compromis.

70
Scott Saunders

La première chose que vous devez décider est une politique générale indiquant quel côté est considéré comme faisant autorité en cas de changements contradictoires.

C'est-à-dire que supposons que l'enregistrement n ° 125 soit modifié sur le serveur le 5 janvier à 22 heures et que le même enregistrement soit modifié sur l'un des téléphones (appelons-le client A) le 5 janvier à 23 heures. La dernière synchronisation a eu lieu le 3 janvier. Ensuite, l’utilisateur se reconnecte le 8 janvier, par exemple.

Identifier ce qui doit être changé est "facile" dans le sens où le client et le serveur connaissent la date de la dernière synchronisation, donc tout créé ou mis à jour (voir ci-dessous pour plus d'informations) depuis la dernière synchronisation requise être réconcilié.

Supposons donc que le seul enregistrement modifié soit # 125 . Vous pouvez soit décider que l’un des deux gagne et écrase l’autre, soit vous devez prendre en charge une phase de réconciliation dans laquelle un utilisateur peut choisir la version (serveur ou utilisateur). client) est le bon, écrasant l’autre.

Cette décision est extrêmement importante et vous devez peser le "rôle" des clients. Surtout s'il existe un conflit potentiel non seulement entre le client et le serveur, mais également dans le cas où différents clients peuvent modifier le même enregistrement.

[En supposant que le numéro 125 puisse être modifié par un deuxième client (client B), il est possible que le client B, qui n'a pas encore été synchronisé, fournisse une autre version du même enregistrement, rendant ainsi obsolète la résolution du conflit précédent.]

En ce qui concerne le point "créé ou mis à jour" ci-dessus ... comment pouvez-vous identifier correctement un enregistrement s'il a été créé sur l'un des clients (en supposant que cela ait un sens dans votre domaine de problème)? l'application gère une liste de contacts professionnels. Si le client A dit que vous devez ajouter un John Smith nouvellement créé et que le serveur a un John Smith créé hier par le client D ... créez-vous deux enregistrements parce que vous ne pouvez pas être sûr qu'ils ne sont pas des personnes différentes? Allez-vous demander à l'utilisateur de réconcilier ce conflit aussi?

Les clients sont-ils "propriétaires" d'un sous-ensemble de données? C'est à dire. si le client B est configuré pour être "l'autorité" sur les données de la zone 5, le client A peut-il modifier/créer des enregistrements pour la zone 5 ou non? (Cela faciliterait la résolution des conflits, mais pourrait s’avérer impossible dans votre cas).

En résumé, les principaux problèmes sont les suivants:

  • Comment définir "identité" en considérant que les clients détachés peuvent ne pas avoir accédé au serveur avant la création d'un nouvel enregistrement.
  • La situation précédente, quelle que soit la complexité de la solution, peut entraîner une duplication des données. Vous devez donc prévoir comment les résoudre périodiquement et comment informer les clients que ce qu'ils considéraient comme "l'enregistrement n ° 675" avait été fusionné avec/remplacé par Record # 543
  • Décidez si les conflits seront résolus par fiat (par exemple, "La version du serveur l'emporte toujours sur celle du client si celle-ci a été mise à jour depuis la dernière synchronisation") ou par une intervention manuelle.
  • Dans le cas de fiat, en particulier si vous décidez que le client a la priorité, vous devez également veiller à la façon de traiter avec d'autres clients non synchronisés susceptibles de subir d'autres modifications.
  • Les éléments précédents ne prennent pas en compte la granularité de vos données (afin de simplifier la description). Autant dire qu'au lieu de raisonner au niveau "Enregistrement", comme dans mon exemple, vous trouverez peut-être plus approprié d'enregistrer les modifications au niveau du champ. Ou pour travailler sur un ensemble d'enregistrements (par exemple, enregistrement de personne + enregistrement d'adresse + enregistrement de contact) à la fois, en traitant leur agrégat comme une sorte de "méta-enregistrement".

Bibliographie:

  • Plus sur ceci, bien sûr, sur Wikipedia .

  • Un algorithme de synchronisation simple par l'auteur de Vdirsyncer

  • Article OBJC sur la synchronisation des données

  • SyncML®: Synchroniser et gérer vos données mobiles (Book on O'Reilly Safari)

  • Types de données répliquées sans conflit

  • Réplication optimiste YASUSHI SAITO (Laboratoires HP) et MARC SHAPIRO (Microsoft Research Ltd.) - ACM Computing Surveys, Vol. V, n ° N, 3 2005.

  • Alexander Traud, Juergen Nagler-Ihlein, Frank Kargl et Michael Weber. 2008. Synchronisation cyclique des données via la réutilisation de SyncML. Dans Actes de la neuvième Conférence internationale sur la gestion des données mobiles (MDM '08). IEEE Computer Society, Washington, États-Unis, 165-172. DOI = 10.1109/MDM.2008.10 http://dx.doi.org/10.1109/MDM.2008.10

  • Lam, F., N. Lam et R. Wong. 2002. Synchronisation efficace des données XML mobiles. Dans Actes de la onzième Conférence internationale sur la gestion de l'information et du savoir (McLean, Virginie, États-Unis, du 4 au 9 novembre 2002). CIKM '02. ACM, New York, NY, 153-160. DOI = http://doi.acm.org/10.1145/584792.584820

  • Cunha, P. R. et Maibaum, T. S. 1981. Resource & equil; type de données abstrait + synchronisation - Une méthodologie pour la programmation orientée message -. Dans Actes de la 5ème conférence internationale sur le génie logiciel (San Diego, Californie, États-Unis, 09-12 mars 1981). Conférence internationale sur le génie logiciel. IEEE Press, Piscataway, NJ, 263-272.(Les trois derniers proviennent de la bibliothèque numérique ACM, vous ne pouvez pas savoir si vous êtes membre ou si vous pouvez les obtenir par d'autres canaux).

Depuis le Dr.Dobbs site:.

  • De arxiv.org:

  • A Conflict-Free Replicated JSON Datatype - the paper describes a JSON CRDT implementation (Conflict-free replicated datatypes - CRDTs - are a family of data structures that support concurrent modification and that guarantee convergence of such concurrent updates).
77
p.marino

Je recommanderais que vous ayez une colonne timestamp dans chaque table et chaque fois que vous insérez ou mettez à jour, mettez à jour la valeur timestamp de chaque ligne affectée. Ensuite, vous parcourez toutes les tables en vérifiant si l'horodatage est plus récent que celui de la base de données de destination. Si c'est plus récent, vérifiez si vous devez insérer ou mettre à jour.

Observation 1: tenez compte des suppressions physiques car les lignes sont supprimées de la base de données source et vous devez procéder de la même manière sur la base de données du serveur. Vous pouvez résoudre ce problème en évitant les suppressions physiques ou en enregistrant chaque suppression dans une table avec des horodatages. Quelque chose comme ceci: DeletedRows = (id, table_name, pk_column, pk_column_value, timestamp) Donc, vous devez lire toutes les nouvelles lignes de la table DeletedRows et exécuter une suppression sur le serveur en utilisant nom_table, pk_column et pk_column_value.

Observation 2: soyez conscient de FK car l'insertion de données dans une table liée à une autre table peut échouer. Vous devez désactiver chaque FK avant la synchronisation des données.

6

Si quelqu'un a un problème de conception similaire et doit synchroniser les modifications sur plusieurs appareils Android, je recommande de vérifier Google Cloud Messaging pour Android (GCM).

Je travaille sur une solution où les modifications effectuées sur un client doivent être propagées à d'autres clients. Et je viens de mettre en œuvre une implémentation de validation de principe (serveur et client) et cela fonctionne à merveille.

Fondamentalement, chaque client envoie des modifications delta au serveur. Par exemple. L'identifiant de ressource ABCD1234 est passé de la valeur 100 à 99.

Le serveur valide ces modifications delta par rapport à sa base de données et approuve la modification (le client est synchronisé) et met à jour sa base de données ou rejette la modification (le client est désynchronisé).

Si la modification est approuvée par le serveur, le serveur en informe ensuite les autres clients (à l'exception de celui qui a envoyé le changement delta) via GCM et envoie un message de multidiffusion portant le même changement delta. Les clients traitent ce message et mettent à jour leur base de données.

Ce qui est cool, c’est que ces changements se propagent presque instantanément !!! si ces appareils sont en ligne. Et je n'ai pas besoin de mettre en œuvre de mécanisme de sondage sur ces clients.

N'oubliez pas que si un périphérique est hors ligne trop longtemps et qu'il y a plus de 100 messages en attente de remise dans la file d'attente GCM, GCM supprimera ce message et enverra un message spécial lorsque le périphérique sera remis en ligne. Dans ce cas, le client doit effectuer une synchronisation complète avec le serveur.

Consultez également ce tutoriel pour vous familiariser avec l’implémentation du client CGM.

5
jogo

cela répond aux développeurs qui utilisent le framework Xamarin (voir https://stackoverflow.com/questions/40156342/sync-online-offline-data )

Un moyen très simple d’atteindre cet objectif avec la structure xamarin consiste à utiliser la synchronisation des données hors connexion d’Azure, car elle permet de transférer et de récupérer des données du serveur à la demande. Les opérations de lecture sont effectuées localement et les opérations d'écriture sont poussées à la demande. Si la connexion réseau est interrompue, les opérations d'écriture sont mises en file d'attente jusqu'à ce que la connexion soit restaurée, puis exécutées.

La mise en oeuvre est assez simple:

1) créer une application mobile dans le portail Azure (vous pouvez l’essayer gratuitement ici https://tryappservice.Azure.com/ )

2) connectez votre client à l'application mobile . https://Azure.Microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started/

3) le code pour configurer votre référentiel 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) Ensuite, poussez et extrayez vos données pour vous assurer que nous avons les dernières modifications:

await this.MobileService.SyncContext.PushAsync();
await this.saleItemsTable.PullAsync("allFoos", fooTable.CreateQuery());

https://Azure.Microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started-offline-data/

5
Ben Ishiyama-Levy

Je vous suggère également de regarder Symmetricds . c'est une bibliothèque de réplication SQLite disponible pour les systèmes Android. vous pouvez l'utiliser pour synchroniser votre base de données client et serveur, je suggère également d'avoir des bases de données distinctes sur le serveur pour chaque client. Essayer de conserver les données de tous les utilisateurs dans une base de données mysql n’est pas toujours la meilleure idée. Spécialement si les données utilisateur vont croître rapidement.

0