Direkt zum Inhalt wechseln

Eventual Consistency in der Microservice Architektur

Daten in Microservices teilen

Keine Angst vor Redundanz. Daten in Microservices richtig teilen.

TL;DR: Um den vollen Nutzen aus dem Einsatz von Microservices zu ziehen, müssen diese komplett entkoppelt sein. Diese Entkopplung macht vielen Entwicklern Angst, da man plötzlich mit Eventual Consistency zurechtkommen muss. Es gibt jedoch Möglichkeiten, damit umzugehen.

Auf der OOP 2024 hat ein Vortrag von Lars Röwekamp den Fokus auf einen Punkt gelenkt, der im Architekten-Alltag zu ernsthaften Problemen führen kann: Eventual Consistency in Microservices.

Eventual Consistency wirkt auf den ersten Blick immer wie das größte Übel, mit dem man zu kämpfen hat, wenn man Microservices einsetzen möchte: “Zeiten von rund einer Sekunde zwischen dem Anlegen von Daten bis zu deren korrekten Anzeige im UI? Das kann ich meinen Nutzern doch unmöglich zumuten!” Oder etwa doch? Laut Lars Röwekamp sind Benutzer nicht-transaktionales Verhalten gewöhnt. So sei selbst eine Banktransaktion, die ja bereits das Wort “Transaktion” im Namen trägt, nicht transaktional im Sinne einer Datenbank-Transaktion. Das Geld wird also nicht vom Konto des Zahlenden abgebucht und zur selben Zeit auf das Konto des Zahlungsempfängers eingezahlt. Dazwischen können gerne mal ein paar Tage vergehen. Denn genau mit diesen Tagen verdient die Bank ihr Geld, indem sie den Überweisungsbetrag mit gutem Ertrag anlegt.
Sollte es dem Kunden bzw. dem Nutzer dennoch wichtig sein, das UI direkt korrekt anzuzeigen, dann kann der Microservice, der in dem Fall als Data Owner agiert, die erstellten Daten zurückgeben, sodass das Frontend diese anzeigen kann.

Wie teile ich Daten in Microservices sicher und nutzerfreundlich?

Hier ein Beispiel für Microservice Data Replication in einem Onlineshop: Angenommen, es gibt die beiden Microservices “Adressen” und “Kasse”.

  1. Über den “Adressen”-Service kann der Nutzer Liefer- und Rechnungsadressen pflegen. Außerdem kann er jeweils eine Standardadresse definieren.
  2. Der “Kasse”-Microservice hält die Standardadressen redundant vor. Diese bekommt er via Domain Event über einen Event Bus geschickt.

Nun möchte der Nutzer während des Bestellvorgangs gerne seine Standard-Lieferadresse ändern. Also führt er im UI die notwendigen Operationen durch. Dadurch wird ein Request an den “Adressen”-Service geschickt, der die neue Standadresse beinhaltet. Doch bevor die Änderung über den Event Bus an den “Kasse”-Service propagiert wurde, wird der Nutzer bereits auf die Seite mit der Bestellzusammenfassung weitergeleitet.
Es wäre schlecht, wenn dort die alte Adresse angezeigt würde. Dann würde der Nutzer glauben, dass seine Änderung nichts bewirkt hat. Um das zu vermeiden, könnte die zuvor ausgewählte Adresse direkt im UI angezeigt werden – selbst wenn der “Kasse”-Service diese noch gar nicht kennt.

Risiko: Was passiert, wenn das Domain Event verloren geht, und der “Kasse”-Service deshalb zum Zeitpunkt des Abschickens der Bestellung immer noch die alte Standardadresse hat?
Lösung: Um dies zu vermeiden, kann das UI beim Abschicken der Bestellung die gewünschte Adresse mitschicken. Der “Kasse”-Service kann dann vor der Verarbeitung der Bestellung einen Abgleich durchführen, und für den Fall, dass die Daten nicht übereinstimmen, eine Fehlermeldung ausgeben.