Synchronisation des bases de données client-serveur

je suis à la recherche de quelques stratégies générales pour synchroniser des données sur un serveur central avec des applications client qui ne sont pas toujours en ligne.

dans mon cas particulier, j'ai une application de 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 seront en mesure d'ajouter et de modifier des informations sur l'application téléphone et sur le web application. Je dois m'assurer que les changements faits à un endroit sont reflète partout même lorsque le téléphone n'est pas en mesure de communiquer immédiatement avec le serveur.

Je ne suis pas concerné par la façon de transférer des données du téléphone vers le serveur ou vice versa. Je ne mentionne mes technologies particulières que 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 a été autour pendant une longue, longue période et voudrait des informations - articles, livres, conseils, etc - sur les modèles pour traiter le problème. J'aimerais connaître les stratégies générales de synchronisation pour comparer les forces, les faiblesses et les compromis.

67
demandé sur Jonas 2010-08-04 19:06:45

5 réponses

la première chose que vous devez décider est une politique générale à propos de quel côté est considéré comme" autoritaire " en cas de changements contradictoires.

c'est-à-dire: supposons que L'enregistrement # 125 soit modifié sur le serveur le 5 janvier à 22h et que le même enregistrement soit modifié sur l'un des téléphones (appelons-le Client A) le 5 janvier à 23h. La dernière synchronisation a eu lieu le 3 janvier. Puis l'utilisateur se reconnecte, disons, le 8 janvier.

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

donc, supposons que le seul enregistrement modifié soit #125. Soit vous décidez que l'un des deux "gagne" automatiquement et écrase l'autre, soit vous devez supporter une phase de réconciliation où un utilisateur peut décider quelle version (serveur ou client) est la bonne., l'écrasement de l'autre.

cette décision est extrêmement importante et vous devez pondérer le" rôle " des clients. En particulier s'il y a un conflit potentiel non seulement entre le client et le serveur, mais dans le cas où des clients différents peuvent changer le(S) même (s) enregistrement (s).

[en supposant que # 125 puisse être modifié par un second client (Client B) il y a une chance que le Client B, qui n'a pas encore synchronisé, fournira encore une autre version du même document, ce qui précédent de la résolution des conflits moot]

concernant le créé ou mis à jour " point ci-dessus... comment pouvez-vous identifier correctement un enregistrement s'il a été émis sur l'un des clients (en supposant que cela a du sens dans votre domaine de problème)? Supposons que votre application gère une liste de contacts d'affaires. 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... ne vous créez deux dossiers parce que vous ne pouvez pas être certain qu'ils ne sont pas des personnes différentes? Allez-vous demander à l'utilisateur de concilier ce conflit?

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 pour la zone #5, Le Client A peut-il modifier/créer des enregistrements pour la zone #5 ou non? (Cela faciliterait la résolution de certains conflits, mais pourrait s'avérer irréalisable pour votre situation).

Pour résumer les principaux problèmes sont:

  • comment définir "identité" considérant que les clients détachés peuvent ne pas avoir accédé au serveur avant de créer un nouvel enregistrement.
  • la situation antérieure, quelle que soit la sophistication de la solution, peut entraîner la 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èrent comme "Record #675" a en fait été fusionné avec / remplacé par le Record #543
  • Décider si les conflits seront résolu par fiat (par exemple "la version du serveur l'emporte toujours sur celle du client si la première a été mise à jour depuis la dernière synchronisation") ou par une intervention manuelle
  • dans le cas de fiat , surtout si vous décidez que le client a la priorité, vous devez également prendre soin de la façon de traiter avec d'autres clients non encore synchronisés qui peuvent avoir d'autres changements à venir.
  • les postes précédents ne prennent pas en compte le la granularité de vos données (afin de rendre les choses plus simples à décrire). Il suffit de dire qu'au lieu de raisonner au niveau "Record", comme dans mon exemple, vous pourriez trouver plus approprié d'enregistrer le changement au niveau du terrain, à la place. Ou pour travailler sur un ensemble d'enregistrements (par exemple L'enregistrement de la personne + L'enregistrement de l'adresse + l'enregistrement des Contacts) à un moment traitant leur agrégat comme une sorte de "méta-enregistrement".

Bibliographie:

(les trois derniers sont de la Bibliothèque numérique ACM, aucune idée si vous êtes un membre ou si vous pouvez obtenir ces Via d'autres canaux).

From the Dr. Dobbs site:

  • Création d'Applications avec SQL Server CE et SQL RDA par le projet de Loi Wagner 19 Mai, 2004 (Meilleures pratiques pour la conception d'une application pour le bureau mobile et PC - Windows/.NET)

de arxiv.org:

  • a Conflict-Free Replicated JSON Datatype - l'article décrit une implémentation JSON CRDT (Conflict-free replicated datatypes - CRDTs - are a family of data structures that support concurrent modification and that guarantee convergence of such concurrent updates).
75
répondu p.marino 2016-11-21 11:23:02

si quelqu'un est confronté à un problème de conception similaire et a besoin de synchroniser les changements à travers plusieurs appareils Android, je recommande de cocher messagerie Cloud de Google pour Android (GCM).

je travaille sur une solution où les changements effectués sur un client doivent être propagés à d'autres clients. Et je viens d'implémenter une implémentation de validation de concept (server & client) et cela fonctionne comme un charme.

En Gros, chaque client envoie delta modifie le serveur. Par exemple: l'id de la ressource ABCD1234 est passé de la valeur 100 à la valeur 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 le changement est approuvé par le serveur, le serveur avertit alors les autres clients (à l'exclusion de celui qui a envoyé le changement delta) via GCM et envoie un message multicast même changement de 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 d'implémenter un mécanisme d'interrogation sur les clients.

gardez à l'esprit que si un périphérique est déconnecté trop longtemps et qu'il y a plus de 100 messages en attente dans la file D'attente GCM pour la livraison, GCM rejettera ces messages et enverra un message spécial lorsque le appareils sera de retour en ligne. Dans ce cas, le client doit faire une synchronisation avec le serveur.

vérifier aussi ce tutoriel pour commencer avec la mise en œuvre client CGM.

5
répondu jogo 2015-01-16 12:12:09

je recommande que vous ayez une colonne timestamp dans chaque tableau et chaque fois que vous insérez ou mettez à jour, mettez à jour la valeur timestamp de chaque ligne affectée. Ensuite, vous itérez toutes les tables en vérifiant si l'horodatage est plus récent que celui que vous avez dans 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: soyez conscient des suppressions physiques car les lignes sont supprimées de la source db et vous avez pour faire la même chose au serveur de db. Vous pouvez résoudre cela en évitant les suppressions physiques ou la journalisation de chaque suppressions dans une table avec des horodateurs. 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 table_name, pk_column et pk_column_value.

Observation 2: soyez conscient de FK car l'insertion de données dans une table qui se rapporte à une autre table pourrait échouer. Vous devez désactiver chaque FK avant les données synchronisation.

5
répondu Francisco Goldenstein 2016-02-28 08:02:33

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

un moyen très simple d'y parvenir avec le framework xamarin est d'utiliser la synchronisation hors ligne des données de L'Azure car elle permet de pousser et de tirer des données du serveur à la demande. Les opérations de lecture se font localement, et les opérations d'écriture sont poussées à la demande; si la connexion réseau casse, les opérations d'écriture sont en file d'attente jusqu'à ce que la connexion soit rétablie, puis exécutée.

la mise en œuvre 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 dépôt 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) puis de pousser et tirer vos données pour s'assurer que nous avons les derniers changements:

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 /

4
répondu Ben Ishiyama-Levy 2017-05-23 12:10:28

je vous suggère aussi de jeter un oeil à Symmetricds . il s'agit d'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. En essayant de contenir 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 de l'utilisateur va se développer rapidement.

0
répondu Hossein Shahdoost 2018-06-06 11:56:38