PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Datenstruktur zwischen Rechnern synchronisieren


creave
2011-06-05, 20:53:50
Hallo!

Für einige von euch mag folgendes relativ trivial sein, aber wenn man wie ich wenig mit Netzwerkprogrammierung und Threading zu tun hat, dann kommt man da schon mal ins Grübeln. Die Technologie ist mir eigentlich egal, aufgrund der hohen Abstraktion und Vorwissen wäre mir jedoch Java recht.

Kurz gesagt besitzen alle Teilnehmer eines Netzwerkdienstes eine lokale Datenstruktur, sagen wir mal eine Liste. Jeder Client kann beliebig viele Einträge in seine lokale Liste schreiben. Ziel soll jedoch sein, dass die Listen untereinander synchronisiert werden und im Endeffekt jeder die gleiche lokale Liste besitzt (gleich bezüglich des Inhalts). Wenn Teilnehmer A seine Liste um den Eintrag X erweitert, so sollen via Server auch die Listen der Teilnehmer B und C um den Eintrag X erweitert werden. Optional wäre es sehr gut, wenn die Reihenfolge der Elemente innerhalb der Listen ebenfalls synchron ist.

Das ganze ist zwar nicht arg zeitkritisch, auf Polling würde ich dennoch gerne verzichten. Die "Updates" sollten schon möglichst live sein, Verzögerungen bis drei oder vier Sekunden wären ok (zu übertragende Datengröße und Netzwerkqualität mal ausgeblendet). Das spricht ja eigentlich für eine bidirektionale Kommunikation zwischen Client und Server, nur wie ist die Frage.

Sockets sind ja nie falsch, aber irgendwie aufwändig. Alles was einen Application Server braucht fällt eigentlich auch weg, da der Server in die Clients integriert sein soll und einer davon eben gleichzeitig Server und Client spielt. Dann fällt mir nur noch RMI ein, aber das ist in seiner Reinform vorerst auch nur unidirektional. Und Callbacks (die ich noch nicht ganz Begriffen habe) sind denke ich anfällig bezüglich Firewalls etc., aber zur Not wäre das ok.

Am liebsten wäre mir es, wenn so viel explizite Arbeit mit Threads wie nur möglich wegfällt. Bei RMI erstellt der Server zumindest für Clientanfragen aus anderen JVMs einen neuen Thread, das müsste man bei Sockets alles selber machen.


Wie würdet ihr das ganze lösen? Vielen Dank und schönen Abend.

edit: freue mich übrigens über Vorschläge aller Art. Also angefangen bei der Strategie bis hin zur Umsetzung. Aufgrund meiner geringen Erfahrung in dem Bereich habe ich dann später auch Detailfragen, aber alles zu seiner Zeit :)

Der_Donnervogel
2011-06-05, 23:06:04
Eine mögliche, einfache, Strategie für das Problem wäre folgender Ansatz:

Es wird nie direkt etwas zur lokalen Liste des Clients hinzugefügt. Wenn bei einem Client etwas hinzugefügt (oder geändert oder was auch immer) werden soll, dann wird dieses Kommando zum Server weitergeleitet. Dort wird die Operation ausgeführt. Falls die Operation fehlschlägt wird die Nachricht verworfen und eine Fehlermeldung an den Client geschickt. Falls sie erfolgreich ist, wird die Nachricht mit der Operation an alle Clients geschickt, die sich beim Server registriert haben. Auf diese Art haben immer alle Clients den selben Stand und man umgeht alle Probleme die aus der Synchronisierung entstehen können.

Nachteilig ist allerdings, dass es schlecht skaliert, da der Server auf diese Art einen Flaschenhals bildet. Außerdem kann es zu Lags kommen, während der Client auf die Antwort des Servers wartet. Falls man mit den Problemen leben kann, dann ist dieser Ansatz aber einfach zu implementieren.

Trap
2011-06-06, 01:09:09
Für einige von euch mag folgendes relativ trivial sein, aber wenn man wie ich wenig mit Netzwerkprogrammierung und Threading zu tun hat, dann kommt man da schon mal ins Grübeln.
Das ist in der allgemeinen Form des Problems kein bisschen trivial. Kannst ja da mal rein gucken: http://en.wikipedia.org/wiki/Distributed_data_store

Wenn man sich auf Hinzufügen in eine Liste als einzige mögliche Operation beschränkt, die Reihenfolge egal ist und es keine harten Zeitanforderungen gibt, dann ist es ein einigermaßen lösbare Aufgabe. Da bleibt als einziges Problem die Daten möglichst performant und zuverlässig an jeden anderen Teilnehmer weiterzugeben.

creave
2011-06-06, 19:14:45
Danke mal soweit.

Also eine Liste auf dem Server müsste es denke ich schon geben, da wohl nur so eine tatsächliche Reihenfolge der Einträge herzustellen ist. Desweiteren kann es clients geben, die sich erst später "einklinken" und es wäre schön, wenn diese trotzdem alle Daten besitzen, auch die, die zeitlich vor dem Connecten vorhanden waren.

Um es nicht zu schwierig zu machen sage ich einfach mal, dass maximal 7-8 Clients erlaubt sind. Ein Eintrag, welcher von einem Client versendet wird (und vom Server verteilt werden soll), ist ca. 1kb groß. Ein Client schickt im Extremfall alle 2 Sekunden solch einen Eintrag.

Was würdet ihr denn als Technologie in Betracht ziehen?

Ich mache jetzt mal einen ganz naiven Vorschlag ins Blaue (naiv, da mangelnde Erfahrung):

Auf Serverseite nutze ich einen RMI-Server. Dieser besitzt eine threadsafe List zur Speicherung der Einträge, die List gibt gleichzeitig die Rangfolge vor. Der RMI-Server besitzt desweiteren Methoden wie z.B. "addNewListEntry(Entry e)", welche den Clients zur Verfügung stehen.
Wenn ich mich nicht irre, dann startet der RMI-Server für jeden Methodenaufruf durch Clients einen eigenen Thread - damit hätte ich wenigstens die eingehenden Verbindungen erschlagen.
Dann brauche ich noch etwas, was die List auf Änderungen überwacht. Ist dies der Fall, so wird in einem expliziten neuen Thread die Änderung verteilt.
Dazu müsste ich mir Callbacks mit RMI noch anschauen, im wesentlichen braucht man wohl noch eine zweite Liste, um die Clients darin zu speichern.

Ganz blöd oder grob brauchbar?
Könnte wetten, dass es mit dem Threading richtig nach hinten losgeht. Kann ich denn die durch Clients aufgerufende Add-Methode (welche implizit in zig threads läuft) einfach so simultan Dinge in die Liste eintragen lassen? Was die Reihenfolge angeht, wer zuerst kommt malt zuerst.