Assignment Chef icon Assignment Chef
All German tutorials

Programming lesson

Zwei-Phasen-Commit für Gruppenfoto-Collagen: Ein verteilter Transaktionsleitfaden

Lerne, wie du mit dem Zwei-Phasen-Commit-Protokoll verteilte Transaktionen implementierst, um Gruppenfoto-Collagen zuverlässig zu veröffentlichen – inklusive Fehlerbehandlung und Wiederherstellung.

Zwei-Phasen-Commit verteilte Transaktionen Java 2PC Implementierung Group Photo Collage Projekt Nachrichtenverlust behandeln Knotenausfall Wiederherstellung CommitServing Interface ProjectLib send receive Autolab Projekt 4 verteilte Systeme Tutorial Gruppenfoto Collage Algorithmus Fehlerbehandlung verteilte Systeme Java UDP Nachrichtendienst persistenter Log Speicher gleichzeitige Transaktionen Studentenprojekt verteilte Systeme

Einführung in das Zwei-Phasen-Commit für Gruppenfoto-Collagen

Stell dir vor, du organisierst ein digitales Gruppenfoto mit Freunden – jeder steuert ein Bild bei, und ein Server erstellt eine Collage. Damit alle zufrieden sind und kein Bild mehrfach verwendet wird, braucht es ein robustes Protokoll: das Zwei-Phasen-Commit (2PC). Dieses verteilte Transaktionsprotokoll stellt sicher, dass entweder alle Teilnehmer zustimmen (Commit) oder die Aktion abgebrochen wird (Abort). In diesem Tutorial lernst du, wie du 2PC in Java implementierst, mit Fokus auf Nachrichtenverlust, Knotenausfälle und Wiederherstellung.

Grundlagen des Zwei-Phasen-Commit

Das Zwei-Phasen-Commit-Protokoll besteht aus zwei Phasen:

  1. Abstimmungsphase (Voting Phase): Der Koordinator (Server) sendet eine Prepare-Nachricht an alle Teilnehmer (UserNodes). Jeder Teilnehmer stimmt mit Yes oder No ab.
  2. Entscheidungsphase (Decision Phase): Wenn alle Yes stimmen, sendet der Koordinator Commit; sonst Abort. Die Teilnehmer setzen die Entscheidung um.

In deinem Projekt werden Collagen per startCommit an den Server übergeben. Der Server startet dann einen 2PC für die beteiligten UserNodes. Jeder UserNode fragt den Benutzer mit askUser, ob die Collage gefällt. Nur bei einstimmiger Zustimmung wird die Collage veröffentlicht und die Quellbilder werden gelöscht.

Implementierung des Servers

Dein Server muss das Interface CommitServing implementieren. Die Methode startCommit erhält den Collage-Dateinamen, den Inhalt und ein Array von Quellbild-Strings (Format: "address:filename").

public class Server implements CommitServing {
    public void startCommit(String filename, byte[] collage, String[] sources) {
        // 1. Extrahiere UserNode-Adressen aus sources
        // 2. Sende PREPARE an alle beteiligten UserNodes
        // 3. Sammle Antworten mit Timeout (3 Sekunden)
        // 4. Entscheide: Commit oder Abort
        // 5. Sende Entscheidung und schreibe ggf. Collage
    }
}

Wichtig: Verwende ProjectLib.send() und receive() für die Kommunikation. Keine Sockets oder Dateisystem-Tricks!

Nachrichtenverlust behandeln

Da Nachrichten verloren gehen können, musst du Timeouts und Wiederholungen einbauen. Nutze dazu Timer oder einen separaten Thread. Wenn innerhalb von 3 Sekunden keine Antwort kommt, nimm an, dass die Nachricht verloren ist, und wiederhole die Anfrage oder breche ab.

Implementierung des UserNode

Jeder UserNode läuft als eigener Prozess und erhält Kommandozeilenargumente: Port und Adresse. Er muss auf PREPARE-Nachrichten reagieren:

public class UserNode {
    public static void main(String[] args) {
        ProjectLib lib = new ProjectLib(Integer.parseInt(args[0]), args[1]);
        while (true) {
            Message msg = lib.receive();
            if (msg.type == PREPARE) {
                boolean approved = lib.askUser(msg.collage);
                lib.send(coordinator, new Message(approved ? YES : NO));
            } else if (msg.type == COMMIT) {
                // Lösche Quellbilder aus Arbeitsverzeichnis
            } else if (msg.type == ABORT) {
                // Nichts tun
            }
        }
    }
}

Wichtig: Jedes Bild darf nur in einer veröffentlichten Collage vorkommen. Führe daher eine lokale Buchhaltung über bereits verwendete Bilder.

Fehlerbehandlung und Wiederherstellung

Wenn ein UserNode während der Abstimmung abstürzt, muss der Server nach einem Neustart den Zustand wiederherstellen. Dazu protokollierst du alle wichtigen Ereignisse in einer Logdatei (persistenter Speicher). Nach einem Neustart liest der Server das Log und setzt die ausstehenden Transaktionen fort.

Beispiel-Log-Einträge:

  • START tx1: collage.jpg, [user1:img1, user2:img2]
  • PREPARE_SENT tx1 to user1
  • YES_RECEIVED tx1 from user1
  • DECISION tx1: COMMIT

Nach einem Crash kann der Server alle Transaktionen im Zustand PREPARE_SENT erneut anfragen oder abbrechen.

Gleichzeitige Collagen verwalten

Dein System muss mehrere Collagen gleichzeitig verarbeiten können. Verwende dazu eine Thread-freundliche Datenstruktur (z. B. ConcurrentHashMap) für aktive Transaktionen. Jede Transaktion läuft in einem eigenen Thread oder wird asynchron behandelt. Achte darauf, dass sich die Ressourcen (Bilder) nicht überschneiden – ein Bild kann nur in einer Transaktion vorkommen.

Testen mit Autolab

Du hast 10 kostenlose Einreichungen pro Checkpoint. Nutze sie weise! Teste lokale Szenarien:

  • Alle stimmen zu → Collage wird veröffentlicht.
  • Ein UserNode lehnt ab → Collage wird verworfen.
  • Nachrichtenverlust → Timeout und Wiederholung.
  • Knotenausfall → Wiederherstellung nach Neustart.

Ein typischer Fehler: Der Server sendet COMMIT, aber der UserNode erhält es nicht. Dann bleibt die Collage beim Server, aber die Bilder werden nicht gelöscht. Dein Protokoll sollte solche Fälle durch erneutes Senden der Entscheidung abdecken.

Trend-Beispiel: KI-generierte Gruppenfotos

Stell dir vor, du und deine Freunde nutzen eine KI-App, um ein gemeinsames Gruppenfoto zu generieren. Jeder lädt ein Selfie hoch, die KI kombiniert sie zu einem perfekten Bild. Damit niemand sein Selfie doppelt verwendet, läuft im Hintergrund ein 2PC: Der Server fragt alle, ob das Ergebnis okay ist. Nur wenn alle zustimmen, wird das KI-Bild gespeichert und die Selfies gelöscht. Genau das baust du hier – aber ohne KI, nur mit einfachen Bildern.

Zusammenfassung

Das Zwei-Phasen-Commit-Protokoll ist ein bewährtes Verfahren für verteilte Transaktionen. In diesem Projekt lernst du, es in Java zu implementieren, mit Fokus auf Robustheit gegenüber Netzwerkfehlern und Ausfällen. Mit sauberem Logging und klugen Timeouts meisterst du auch knifflige Szenarien. Viel Erfolg bei deiner Implementierung!