wake-up-neo.com

Client-Server-Datenbanken synchronisieren

Ich suche nach allgemeinen Strategien zum Synchronisieren von Daten auf einem zentralen Server mit Client-Anwendungen, die nicht immer online sind.

In meinem speziellen Fall habe ich eine Android-Telefonanwendung mit einer SQLite-Datenbank und eine PHP - Webanwendung mit einer MySQL-Datenbank. 

Benutzer können Informationen in der Telefonanwendung und in der Webanwendung hinzufügen und bearbeiten. Ich muss sicherstellen, dass Änderungen, die an einem Ort vorgenommen wurden, überall angezeigt werden, auch wenn das Telefon nicht sofort mit dem Server kommunizieren kann.

Es geht mir nicht darum, wie man Daten vom Telefon zum Server überträgt oder umgekehrt. Ich erwähne meine speziellen Technologien nur, weil ich beispielsweise die für MySQL verfügbaren Replikationsfunktionen nicht verwenden kann.

Ich weiß, dass das Client-Server-Datensynchronisierungsproblem seit langem existiert und möchte Informationen (Artikel, Bücher, Ratschläge usw.) über Muster zur Behandlung des Problems. Ich würde gerne allgemeine Strategien für den Umgang mit Synchronisation kennenlernen, um Stärken, Schwächen und Kompromisse zu vergleichen.

70
Scott Saunders

Als erstes müssen Sie eine allgemeine Richtlinie darüber festlegen, welche Seite als "autoritär" bezeichnet wird, wenn sich Änderungen ergeben.

Beispiel: Nehmen Sie an, der Datensatz # 125 wird am 5. Januar um 22:00 Uhr auf dem Server geändert, und derselbe Datensatz wird auf einem der Telefone (nennen wir ihn Client A) am 5. Januar um 23:00 Uhr. Letzte Synchronisation war am 3. Januar. Dann verbindet sich der Benutzer am 8. Januar wieder.

Zu erkennen, was geändert werden muss, ist "einfach" in dem Sinne, dass sowohl der Client als auch der Server das Datum der letzten Synchronisierung kennen, also alles, was erstellt oder aktualisiert wurde (siehe unten), da die letzte Synchronisierung erforderlich ist versöhnt werden.

Nehmen wir an, der einzige geänderte Datensatz ist # 125 . Sie entscheiden entweder, dass einer der beiden automatisch "gewinnt" und überschreibt den anderen, oder Sie müssen eine Abstimmungsphase unterstützen, in der ein Benutzer entscheiden kann, welche Version (Server oder Server) Client) ist der richtige, der andere wird überschrieben.

Diese Entscheidung ist äußerst wichtig und Sie müssen die "Rolle" der Kunden gewichten. Vor allem, wenn ein potenzieller Konflikt nicht nur zwischen Client und Server besteht, sondern auch, wenn verschiedene Clients dieselben Datensätze ändern können.

[Wenn angenommen wird, dass # 125 von einem zweiten Client (Client B) geändert werden kann, besteht die Möglichkeit, dass Client B, der noch nicht synchronisiert wurde, eine weitere Version desselben Datensatzes bereitstellt, wodurch die vorherige Konfliktlösung moot wird.]

Was den Punkt "Created oder Updated" oben angeht ... Wie können Sie einen Datensatz richtig identifizieren, wenn er von einem der Clients stammt (vorausgesetzt, dies macht in Ihrer Problemdomäne Sinn)? Nehmen wir an, Ihr App verwaltet eine Liste von Geschäftskontakten. Wenn Client A sagt, dass Sie einen neu erstellten John Smith hinzufügen müssen, und der Server einen gestern von Client D erstellten John Smith hat ... erstellen Sie zwei Datensätze, weil Sie nicht sicher sein können, dass es sich nicht um unterschiedliche Personen handelt? Fordern Sie den Benutzer auf, diesen Konflikt auch zu lösen?

Verfügen die Kunden über einen Teil der Daten? Das heißt Wenn Client B als "Autorität" für Daten für Area # 5 eingerichtet ist, kann Client A Datensätze für Area # 5 ändern oder erstellen? (Dies würde die Konfliktlösung vereinfachen, kann sich jedoch für Ihre Situation als nicht praktikabel erweisen).

Zusammenfassend sind die Hauptprobleme:

  • Wie definieren Sie "Identität", wenn Sie berücksichtigen, dass getrennte Clients möglicherweise nicht auf den Server zugegriffen haben, bevor Sie einen neuen Datensatz erstellen.
  • Die bisherige Situation, egal wie ausgereift die Lösung ist, kann zu einer Duplizierung der Daten führen. Daher müssen Sie vorhersehen, wie diese regelmäßig gelöst werden müssen, und wie Sie die Clients darüber informieren, dass das, was sie als "Datensatz # 675" betrachten, tatsächlich mit/zusammengelegt wurde Datensatz # 543
  • Legen Sie fest, ob Konflikte durch fiat gelöst werden sollen (z. B. "Die Serverversion übertrumpft immer die Clientversion, wenn die Erstversion seit der letzten Synchronisierung aktualisiert wurde") oder durch manuelles Eingreifen
  • Im Falle von fiat, insbesondere wenn Sie entscheiden, dass der Client Vorrang hat, müssen Sie auch darauf achten, wie mit anderen, noch nicht synchronisierten Clients verfahren wird, bei denen möglicherweise weitere Änderungen bevorstehen.
  • Die vorherigen Elemente berücksichtigen nicht die Granularität Ihrer Daten (um die Beschreibung zu vereinfachen). Es genügt zu sagen, dass Sie anstelle der Argumentation auf "Record" -Ebene, wie in meinem Beispiel, die Änderungen eher auf Feldebene als angemessener empfinden. Oder um an einem Satz von Datensätzen (z. B. Personendatensatz + Adressdatensatz + Kontaktdatensatz) zu arbeiten, wobei ihr Aggregat als eine Art "Metadatensatz" behandelt wird.

Literaturverzeichnis:

  • Mehr dazu natürlich auf Wikipedia .

  • Ein einfacher Synchronisationsalgorithmus vom Autor von Vdirsyncer

  • OBJC-Artikel zur Datensynchronisation

  • SyncML®: Synchronisieren und Verwalten Ihrer mobilen Daten (Buch bei O'Reilly Safari)

  • Konfliktfreie replizierte Datentypen

  • Optimistische Replikation YASUSHI SAITO (HP Laboratories) und MARC SHAPIRO (Microsoft Research Ltd.) - ACM Computing Surveys, Vol. V, Nr. N, 3 2005.

  • Alexander Traud, Jürgen Nagler-Ihlein, Frank Kargl und Michael Weber. 2008. Zyklische Datensynchronisation durch Wiederverwendung von SyncML. In den Verfahren der Neunten Internationalen Konferenz zum Mobile Data Management (MDM '08). IEEE Computer Society, Washington, DC, USA, 165-172. DOI = 10.1109/MDM.2008.10 http://dx.doi.org/10.1109/MDM.2008.10

  • Lam, F., Lam, N. und Wong, R. 2002. Effiziente Synchronisation für mobile XML-Daten. In Proceedings der elften internationalen Konferenz über Informations- und Wissensmanagement (McLean, Virginia, USA, 4.-9. November 2002). CIKM '02. ACM, New York, NY, 153-160. DOI = http://doi.acm.org/10.1145/584792.584820

  • Cunha, P. R. und Maibaum, T. S. 1981. Resource & equil; Abstrakter Datentyp + Synchronisation - Eine Methode zur nachrichtenorientierten Programmierung -. In Proceedings der 5. internationalen Konferenz über Software Engineering (San Diego, Kalifornien, USA, 9. - 12. März 1981). Internationale Konferenz über Software Engineering. IEEE Press, Piscataway, NJ, 263-272.(Die letzten drei stammen aus der digitalen ACM-Bibliothek. Keine Ahnung, ob Sie Mitglied sind oder über andere Kanäle abgerufen werden können).

Von der Dr.Dobbs Site:.

  • Von 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

Ich würde empfehlen, dass Sie in jeder Tabelle eine timestamp -Spalte haben und bei jedem Einfügen oder Aktualisieren den Timestamp-Wert jeder betroffenen Zeile aktualisieren. Anschließend durchlaufen Sie alle Tabellen und überprüfen, ob der Zeitstempel neuer als der in der Zieldatenbank ist. Wenn es neuer ist, prüfen Sie, ob Sie Einfügen oder Aktualisieren müssen.

Beobachtung 1: Beachten Sie physische Löschungen, da die Zeilen aus der Quell-Datenbank gelöscht werden und Sie dies auch auf der Server-Datenbank tun müssen. Sie können dieses Problem lösen, indem Sie physische Löschungen vermeiden oder jede Löschung in einer Tabelle mit Zeitstempeln protokollieren. Etwas wie folgt: DeletedRows = (id, table_name, pk_column, pk_column_value, timestamp) Sie müssen also alle neuen Zeilen der DeletedRows-Tabelle lesen und auf dem Server ein Löschen mit table_name, pk_column und pk_column_value ausführen.

Anmerkung 2: Beachten Sie FK, da das Einfügen von Daten in eine Tabelle, die sich auf eine andere Tabelle bezieht, möglicherweise fehlschlägt. Sie sollten jeden FK vor der Datensynchronisierung deaktivieren.

Wenn sich jemand mit ähnlichen Designproblemen beschäftigt und Änderungen auf mehreren Android-Geräten synchronisieren muss, empfehle ich die Überprüfung von Google Cloud Messaging für Android (GCM).

Ich arbeite an einer Lösung, bei der Änderungen, die an einem Client vorgenommen wurden, an andere Clients weitergegeben werden müssen. Und ich habe gerade eine Proof-of-Concept-Implementierung implementiert (Server & Client) und es funktioniert wie ein Zauber.

Grundsätzlich sendet jeder Client Delta-Änderungen an den Server. Z.B. Die Ressourcen-ID ABCD1234 wurde von Wert 100 in 99 geändert.

Der Server validiert diese Delta-Änderungen anhand seiner Datenbank und genehmigt entweder die Änderung (Client ist synchronisiert) und aktualisiert die Datenbank oder lehnt die Änderung ab (Client ist nicht synchron).

Wenn die Änderung vom Server genehmigt wurde, benachrichtigt der Server die anderen Clients (mit Ausnahme desjenigen, der die Delta-Änderung gesendet hat) über GCM und sendet eine Multicast-Nachricht mit derselben Delta-Änderung. Clients verarbeiten diese Nachricht und aktualisieren ihre Datenbank.

Coole Sache ist, dass diese Änderungen fast sofort propagiert werden !!! Wenn diese Geräte online sind. Und ich muss auf diesen Clients keinen Abfragemechanismus implementieren.

Wenn ein Gerät zu lange offline ist und sich mehr als 100 Nachrichten in der GCM-Warteschlange befinden, werden diese Nachrichten verworfen. Wenn das Gerät wieder online ist, werden diese Nachrichten vom GCM verworfen. In diesem Fall muss der Client eine vollständige Synchronisierung mit dem Server durchführen.

Überprüfen Sie auch dieses Tutorial , um mit der CGM-Client-Implementierung zu beginnen.

5
jogo

dies beantwortet Entwickler, die das Xamarin-Framework verwenden (siehe https://stackoverflow.com/questions/40156342/sync-online-offline-data ).

Eine sehr einfache Möglichkeit, dies mit dem Xamarin-Framework zu erreichen, besteht in der Verwendung der Offline-Datensynchronisierung von Azure, da auf diese Weise Daten vom Server gepusht und vom Server abgerufen werden können. Lesevorgänge werden lokal ausgeführt und Schreibvorgänge werden bei Bedarf verschoben. Wenn die Netzwerkverbindung abbricht, werden die Schreibvorgänge in die Warteschlange gestellt, bis die Verbindung wiederhergestellt und dann ausgeführt wird.

Die Implementierung ist ziemlich einfach:

1) Erstellen Sie eine Mobile-App im Azure-Portal (Sie können es hier kostenlos ausprobieren https://tryappservice.Azure.com/ )

2) Verbinden Sie Ihren Client mit der mobilen App . https://Azure.Microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started/

3) den Code zum Einrichten Ihres lokalen Repositorys:

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) Dann Push und Pull Ihrer Daten, um sicherzustellen, dass wir die neuesten Änderungen haben:

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

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

5

Ich schlage vor, dass Sie auch einen Blick auf Symmetricds werfen. Es ist eine SQLite-Replikationsbibliothek, die für Android-Systeme verfügbar ist. Sie können es verwenden, um Ihre Client- und Server-Datenbank zu synchronisieren. Ich empfehle außerdem, für jeden Client separate Datenbanken auf dem Server zu haben. Der Versuch, die Daten aller Benutzer in einer MySQL-Datenbank zu speichern, ist nicht immer die beste Idee. Insbesondere, wenn die Benutzerdaten schnell wachsen werden.

0