16 Stimmen

Core Data Cloud-Synchronisierung - ich brauche Hilfe bei der Logik

Ich bin gerade dabei, ein Brainstorming für eine Cloud-Synchronisierungslösung für eine Core Data-Anwendung durchzuführen, die ich derzeit entwickle. Ich plane, den Code dafür als Open Source zu veröffentlichen, sobald er fertig ist, damit jeder ihn mit seinen Core Data-Apps verwenden kann.) Hier ist, was ich denke:

Server-Seite


Anbieter von Speicherplatz

Wie bei allen Cloud-Synchronisationssystemen ist die Speicherung ein wichtiger Teil des Puzzles. Es gibt viele Möglichkeiten, dies zu handhaben. Ich könnte meinen eigenen Server für die Speicherung einrichten oder einen Dienst wie Amazon S3 nutzen, aber da ich im Moment mit 0 $ Kapital anfange, ist eine bezahlte Speicherlösung keine praktikable Option. Nach einiger Überlegung habe ich mich für folgende Lösung entschieden Dropbox (ein bereits gut etablierter Anbieter von Cloud-Synchronisierungsanwendungen und -Speicher). Die Vorteile der Verwendung von Dropbox sind:

  • Es ist kostenlos (für eine begrenzte Menge an Speicherplatz)
  • Neben dem Speicherdienst übernimmt er auch die Synchronisierung mit der Cloud.
  • Kürzlich wurde ein Objective-C SDK veröffentlicht, das die Verwendung in Mac- und iPhone-Anwendungen erheblich erleichtert.

Für den Fall, dass ich mich entschließe, in Zukunft zu einem anderen Speicheranbieter zu wechseln, beabsichtige ich, diesem Cloud-Sync-Framework "Dienste" hinzuzufügen, die es im Grunde jedem ermöglichen, eine Dienstklasse zu erstellen, die eine Schnittstelle zu einem Speicheranbieter seiner Wahl bildet und die dann einfach in das Framework eingefügt werden kann.

Struktur der Lagerung

Dies ist ein wirklich schwieriger Teil, um herauszufinden, so brauche ich so viel Input wie ich kann hier. Ich habe über eine Struktur wie diese nachgedacht:

CloudSyncFramework
======> [app name]
==========> devices
=============> (device id)
================> deviceinfo
================> changeset
==========> entities
=============> (entity name)
================> (object id)

Eine kurze Erklärung zu dieser Struktur:

  • Der Hauptordner "CloudSyncFramework" (Name unbestimmt) wird separate Ordner für jede Anwendung enthalten, die das Framework verwendet
  • Jeder Anwendungsordner enthält eine Geräte Ordner und ein Einrichtungen Ordner
  • En Geräte enthält einen Ordner für jedes Gerät, das für das Konto registriert ist. Der Geräteordner wird nach der Geräte-ID benannt, die Sie etwa wie folgt erhalten [[UIDevice currentDevice] uniqueIdentifier] (unter iOS) oder eine Seriennummer (unter Mac OS).
  • Jeder Geräteordner enthält zwei Dateien: geräteinfo y Änderungssatz . geräteinfo enthält Informationen über das Gerät (z. B. Betriebssystemversion, Datum der letzten Synchronisierung, Modell usw.) und die Änderungssatz Datei enthält Informationen über Objekte, die seit der letzten Synchronisierung des Geräts geändert wurden. Beide Dateien sind einfache NSDictionaries, die in Dateien mit NSKeyedArchiver .
  • Jede Kerndateneinheit hat einen Unterordner unter dem Einrichtungen Ordner
  • Unter jedem Entitätsordner wird für jedes Objekt, das zu dieser Entität gehört, eine eigene Datei angelegt. Diese Datei enthält ein JSON-Wörterbuch mit den Schlüssel-Werte-Paaren.

Gleichzeitige Synchronisierung

Dies ist einer der Bereiche, in denen ich fast völlig ahnungslos bin. Wie kann ich 2 Geräte gleichzeitig mit der Cloud verbinden und synchronisieren? Hier besteht ein hohes Risiko, dass Dinge nicht mehr synchronisiert werden oder sogar Daten beschädigt werden.

Handhabung von Migrationen

Wieder einmal ein weiteres Gebiet, das keine Ahnung hat. Wie würde ich Migrationen des von Core Data verwalteten Objektmodells handhaben? Am einfachsten scheint es zu sein, den Cloud-Datenspeicher zu löschen und eine neue Kopie der Daten von einem Gerät hochzuladen, das den Migrationsprozess durchlaufen hat, aber das scheint etwas riskant zu sein, und vielleicht gibt es einen besseren Weg.

Kunden-Seite


Konvertierung von NSManagedObjects in JSON

Das Konvertieren von Attributen in JSON ist keine sehr schwierige Aufgabe (es gibt jede Menge Code dafür im Web). Beziehungen sind hier das Hauptproblem. In ce Stackoverflow-Beitrag stellt Marcus Zarra einen Code vor, in dem die Beziehungsobjekte selbst dem JSON-Wörterbuch hinzugefügt werden. Er erwähnt jedoch, dass dies je nach der Struktur des Modells zu einer Endlosschleife führen kann, und ich bin nicht sicher, ob dies mit meiner Methode funktionieren würde, da ich jedes Objekt als einzelne Datei speichere.

Ich habe versucht, einen Weg zu finden, um eine ID als Zeichenfolge für eine NSManagedObject . Dann könnte ich Beziehungen in JSON als ein Array von IDs speichern. Am ehesten habe ich folgende Lösung gefunden [[managedObject objectID] URIRepresentation] , aber das ist nicht wirklich eine ID für ein Objekt, seine mehr von einem Speicherort für das Objekt in den persistenten Speicher, und ich weiß nicht, ob seine konkret genug, um als Referenz für ein Objekt zu verwenden.

Ich nehme an, ich könnte eine UUID-Zeichenfolge für jedes Objekt generieren und sie als Attribut speichern, aber ich bin offen für Vorschläge.

Synchronisierung von Änderungen in der Cloud

Die erste (und immer noch beste) Lösung, die mir dafür in den Sinn kam, war das Hören auf die NSManagedObjectContextObjectsDidChangeNotification um eine Liste der geänderten Objekte zu erhalten und diese Objekte dann im Cloud-Datenspeicher zu aktualisieren/löschen/einzufügen. Nachdem die Änderungen gespeichert wurden, müsste ich die Änderungssatz Datei für jedes andere registrierte Gerät, um die neu geänderten Objekte wiederzugeben.

Ein Problem, das sich hier stellt, ist, Wie gehe ich mit einer fehlgeschlagenen oder unterbrochenen Synchronisierung um? . Eine Idee, die ich habe, ist, die Änderungen zunächst in ein temporäres Verzeichnis in der Cloud zu verschieben und dann, sobald dies als erfolgreich bestätigt wurde, mit den Stammdaten in der Cloud zusammenzuführen, damit eine Unterbrechung in der Mitte der Synchronisierung die Daten nicht beschädigt. Dann würde ich Aufzeichnungen der Objekte, die in der Cloud aktualisiert werden müssen, in einer plist-Datei oder ähnlichem speichern, die bei der nächsten Internetverbindung der App übertragen wird.

Abrufen von geänderten Objekten

Dies ist recht einfach, das Gerät lädt seine Änderungssatz Datei, findet heraus, welche Objekte aktualisiert/eingefügt/gelöscht werden müssen, und handelt dann entsprechend.

Und damit sind meine Gedanken zur Logik, die dieses System verwenden wird, zusammengefasst :-) Jede Einsicht, jeder Vorschlag, jede Antwort auf ein Problem usw. ist willkommen. sehr gewürdigt.

アップデイト

Nach langem Nachdenken und der Lektüre von TechZens Vorschlägen habe ich einige Änderungen an meinem Konzept vorgenommen.

Die größte Änderung, die ich mir ausgedacht habe, ist, dass jedes Gerät eine getrennt Datenspeicher in der Cloud. Grundsätzlich gilt, dass jedes Mal, wenn der verwaltete Objektkontext spart (danke TechZen), werden die Änderungen in den Datenspeicher des Geräts hochgeladen. Nachdem diese Änderungen aktualisiert wurden, wird eine "Changeset"-Datei mit den Änderungsdetails erstellt und in den Changeset-Ordnern der ANDEREN Geräte, die die Anwendung verwenden, gespeichert. Wenn die anderen Geräte eine Verbindung zur Synchronisierung herstellen, durchsuchen sie den Änderungssatzordner und wenden jeden Änderungssatz auf den lokalen Datenspeicher an, um dann ihre jeweiligen Datenspeicher in der Cloud ebenfalls zu aktualisieren.

Wenn nun ein neues Gerät für das Konto registriert wird, findet es die neueste Kopie der Daten von allen Geräten und laden Sie diese herunter, um sie als lokalen Speicher zu verwenden. Dies löst das Problem der gleichzeitigen Synchronisierung und verringert die Gefahr der Datenverfälschung, da es keinen "zentralen" Datenspeicher gibt, sondern jedes Gerät nur seine Daten berührt und Änderungen aktualisiert, anstatt dass jedes Gerät gleichzeitig auf dieselben Daten zugreift und sie verändert.

Es gibt einige offensichtliche Konfliktsituationen, die es zu lösen gilt, vor allem in Bezug auf das Löschen von Objekten. Wenn ein Änderungssatz heruntergeladen wird, der die Anwendung anweist, ein Objekt zu löschen, das gerade bearbeitet wird, usw., muss es Möglichkeiten geben, damit umzugehen.

16voto

TechZen Punkte 64117

Betrachten Sie diese pessimistische Sichtweise der Cloud-Synchronisierung: Warum Cloud Sync nie funktionieren wird. Er deckt viele der Probleme ab, mit denen Sie zu kämpfen haben. Viele von ihnen sind weitgehend unlösbar.

Es ist sehr, sehr, sehr schwierig, Informationen zu synchronisieren. Wenn man verschiedene Geräte, unterschiedliche Betriebssysteme, unterschiedliche Datenstrukturen usw. hinzunimmt, wird die Komplexität oft fatal erhöht. Seit den 70er Jahren wird an Varianten dieses Problems gearbeitet, und es hat sich nicht wirklich viel verbessert.

Das Grundproblem besteht darin, dass die Komplexität der Synchronisierung aller Varianten exponentiell mit der Anzahl der Anpassungen steigt, wenn man das System flexibel und anpassbar lässt. Wenn Sie es starr machen, können Sie zwar synchronisieren, aber Sie sind in dem, was Sie synchronisieren können, eingeschränkt.

Wie würde ich mit 2 Geräten umgehen? verbinden und mit der Cloud synchronisieren zur gleichen Zeit?

Wenn Sie das herausfinden, werden Sie reich sein. Es ist ein großes Problem für aktuelle Cloud-Sync-Anbieter. Das eigentliche Problem hier ist, dass Sie nicht "synchronisieren", sondern zusammenführen. Software ist schlecht beim Zusammenführen, weil es sehr schwer ist, einen vordefinierten Regelsatz zu erstellen, der alle möglichen Zusammenführungen beschreibt.

Das einfachste System besteht darin, entweder ein kanonisches Gerät oder eine Gerätehierarchie zu erstellen, so dass das System immer weiß, welcher Eingang zu wählen ist. Dadurch wird jedoch die Flexibilität beeinträchtigt.

Wie würde ich die Migrationen der Core Data verwalteten Objektmodells?

Die Migration des Core Data-Modells ist für den Server weitgehend irrelevant. Das ist etwas, das Core Data intern für sich selbst verwaltet. Die Modellmigration aktualisiert das Modell, d. h. den Entitätsgraphen, nicht die eigentlichen Daten.

Umwandlung von NSManagedObjects in JSON

Die Modellierung von Beziehungen ist schwierig, insbesondere mit Tools, die dies nicht so einfach unterstützen wie Core Data. Die URI einer permanenten verwalteten Objekt-ID soll jedoch als UUID dienen, die das Objekt an einem bestimmten Ort in einem bestimmten Speicher auf einem bestimmten Gerät festhält. Es ist technisch nicht garantiert, dass sie universell eindeutig ist, aber für alle praktischen Zwecke ist sie nahe genug.

Synchronisierung von Änderungen in der Cloud

Ich glaube, Sie verwechseln die Implementierungsdetails von Core Data mit der Cloud selbst. Wenn Sie verwenden NSManagedObjectContextObjectsDidChangeNotification wird jedes Mal, wenn sich der beobachtete Kontext ändert, Netzverkehr ausgelöst, unabhängig davon, ob diese Änderungen beibehalten werden oder nicht. Je nach Anwendung könnte dies in wenigen Minuten tausende von Verbindungen auslösen. Stattdessen sollten Sie nur synchronisieren, wenn der Kontext höchstens gespeichert wird.

Ein Problem, das sich hier stellt, ist, wie ich mit einer fehlgeschlagenen oder unterbrochenen Synchronisierung?

Die Änderungen werden erst nach Abschluss der Synchronisierung übernommen. Dies ist ein großes Problem und führt zu fehlerhaften Daten. Auch hier gilt: Sie können flexibel, komplex und anfällig oder unflexibel, einfach und robust sein.

Abrufen von geänderten Objekten: Dies ist ziemlich einfach, das Gerät lädt seine seine Changeset-Datei herunter, findet heraus, welche Objekte zu aktualisieren aktualisiert/eingefügt/gelöscht werden müssen, und handelt dann entsprechend

Es ist nur einfach, wenn Sie eine unflexible Datenstruktur haben. Die Beschreibung von Änderungen an einer flexiblen Datenstruktur ist ein Alptraum.

Ich bin mir nicht sicher, ob ich etwas bewirkt habe. Für keines der Probleme gibt es elegante Lösungen. Die meisten Designer enden mit Starrheit und/oder einer langsamen, iterativen Zusammenführung mit roher Gewalt.

1voto

Shyam Habarakada Punkte 14267

Werfen Sie einen ernsthaften Blick auf RestKit .

Es handelt sich um ein Open-Source-Projekt, das die Integration von iOS-Apps mit Cloud-Daten unterstützen soll, einschließlich, aber nicht beschränkt auf das Szenario, in dem es ein Kerndatenmodell für diese Daten auf dem Client gibt.

Ich habe vor kurzem damit begonnen, es in einem meiner Projekte zu verwenden, und fand es sehr nützlich. Im Core-Data-Szenario implementieren Sie deklarative Zuordnungen zwischen Ihrem Datenmodell und den Inhalten, die Sie vom Server abrufen und an den Server senden, und es kümmert sich um Dinge wie das Injizieren von Objekten aus der Cloud in Ihr Client-Modell, das Senden neuer Objekte an den Server und das Einbinden von vom Server generierten Objekt-IDs in Ihr Client-seitiges Modell, wobei all dies in einem Hintergrund-Thread geschieht und sich um alle Core-Data-Kontext-Threading-Probleme kümmert und so weiter.

RestKit ist keineswegs ein ausgereiftes Produkt, aber es verfügt über eine recht gute Grundlage und einige Dinge, die Hilfe von anderen Mitwirkenden gebrauchen können. Vor allem, wenn es Ihr Ziel ist, eine Open-Source-Lösung zu schaffen, wäre es großartig, zu etwas wie diesem beizutragen und es zu verbessern, anstatt eine neue Lösung zu erfinden. Es sei denn, Sie sehen gravierende Unterschiede zwischen dem, was Ihnen vorschwebt, und anderen bestehenden Lösungen :-)

1voto

Drew McCormack Punkte 3400

Seit der Veröffentlichung dieses Beitrags gibt es mehrere neue Optionen. Es ist möglich, eine Lösung zu entwickeln, und es gibt Anwendungen, die mit diesen Lösungen ausgeliefert werden.

Im Folgenden finden Sie eine kurze Liste der wichtigsten Optionen für die Synchronisierung von Kerndaten:

  1. Die Apple-eigene Core Data/iCloud-Synchronisierung. (Hatte einen holprigen Start. Scheint jetzt besser zu sein.)
  2. TICDS
  3. Wasabi Sync ein kostenpflichtiger Dienst.
  4. Simperium (Scheint verlassen zu sein.)
  5. PaketKit mit Dropbox Datenspeicher API
  6. Ensembles , die jüngste. (Offenlegung: Ich bin der Gründer des Projekts)

0voto

indragie Punkte 17802

Es ist, als hätte Apple meine Frage mit der Ankündigung des iCloud-SDKs die mit einer Core Data-Integration ausgestattet sind. Gewinnen!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X