Verteilte Datenverwaltung - Implementieren von Microservices in AWS

Verteilte Datenverwaltung

Monolithische Anwendungen werden typischerweise durch eine große relationale Datenbank unterstützt, die ein einziges Datenmodell definiert, das allen Anwendungskomponenten gemein ist. Bei einem Microservice-Ansatz würde eine solche zentrale Datenbank das Ziel, dezentrale und unabhängige Komponenten aufzubauen, verhindern. Jede Microservice-Komponente sollte eine eigene Datenpersistenzschicht haben.

Dezentrales Datenmanagement stellt jedoch neue Herausforderungen dar. Infolge des CAP-Theorem machen verteilte Microservice-Architekturen zugunsten der Leistung Abstriche bei der Konsistenz und müssen einen „Eventually Consistent“-Zustand (letztendliche Datenkonsistenz) erreichen.

In einem verteilten System können Geschäftstransaktionen mehrere Microservices umfassen. Da dabei keine einzelne ACID-Transaktion genutzt werden kann, erfolgt die Transaktion möglicherweise nur zum Teil. In diesem Fall müssten die bereits verarbeiteten Transaktionen mithilfe einer Steuerungslogik wiederhergestellt werden. Zu diesem Zweck wird in der Regel das verteilte Saga-Muster verwendet. Wenn eine Geschäftstransaktion fehlschlägt, orchestriert Saga eine Reihe von kompensierenden Transaktionen, um die während der vorangegangenen Transaktionen durchgeführten Änderungen rückgängig zu machen. AWS Step Functions erleichtert die Implementierung eines Koordinators zur Ausführung von Saga, wie in der nächsten Abbildung dargestellt.

Ausführungskoordinator für Saga

Die Entwicklung eines zentralen Speichers kritischer Referenzdaten, der von Stammdatenmanagement-Tools und -Verfahren kuratiert wird, bietet Microservices die Möglichkeit, ihre kritischen Daten und möglicherweise Wiederherstellungspunkte zu synchronisieren. Mit Lambda und geplanten Amazon CloudWatch Events können Sie einen einfachen Bereinigungs- und Deduplizierungsmechanismus entwickeln.

Es kommt häufig vor, dass Zustandsänderungen mehr als einen einzelnen Microservice betreffen. In diesen Fällen hat sich das Event-Sourcing als nützliches Muster erwiesen. Die Grundidee des Event-Sourcing besteht darin, jede Anwendungsänderung als Ereignisprotokoll darzustellen und beizubehalten. Anstatt den Anwendungszustand zu persistieren, werden die Daten als Ereignisstrom gespeichert. Datenbank-Transaktionsprotokollierung und Versionskontrollsysteme sind zwei bekannte Beispiele für Event-Sourcing. Event-Sourcing hat einige Vorteile: Der Zustand kann zu jedem Zeitpunkt ermittelt und rekonstruiert werden. Es erzeugt auf natürliche Weise einen persistenten Audit-Trail und erleichtert auch das Debugging.

Im Rahmen von Microservice-Architekturen ermöglicht Event-Sourcing die Entkopplung verschiedener Teile einer Anwendung unter Verwendung eines Publish/Subscribe-Musters und speist die gleichen Ereignisdaten in verschiedene Datenmodelle für einzelne Microservices ein. Event-Sourcing wird häufig in Verbindung mit dem CQRS-Muster (Command, Query, Responsibility, Segregation) verwendet, um das Lesen von Schreib-Workloads zu entkoppeln und sowohl Leistung, Skalierbarkeit als auch Sicherheit zu optimieren. In traditionellen Datenmanagementsystemen werden Befehle und Abfragen im selben Datenspeicher ausgeführt.

Die folgende Abbildung zeigt, wie das Event-Sourcing-Muster in AWS implementiert werden kann. Amazon Kinesis Data Streams dient als Hauptkomponente des zentralen Ereignisspeichers, der Anwendungsänderungen als Ereignisse erfasst und dauerhaft in Amazon S3 speichert. Die Abbildung zeigt drei verschiedene Microservices bestehend aus Amazon API Gateway, AWS Lambda und Amazon DynamoDB. Die Pfeile geben den Ablauf der Ereignisse an: Wenn sich der Ereignisstatus des ersten Microservice ändert, veröffentlicht dieser ein Ereignis, indem er eine Nachricht in Kinesis Data Streams schreibt. Alle Microservices führen ihre eigene Kinesis Data Streams-Anwendung in AWS Lambda aus. AWS Lambda liest eine Kopie der Nachricht, filtert sie entsprechend ihrer Relevanz für den Microservice und leitet die Nachricht gegebenenfalls zur weiteren Verarbeitung weiter. Wenn Ihre Funktion einen Fehler zurückgibt, wiederholt Lambda die Batch-Verarbeitung, bis diese erfolgreich ist oder die Daten ablaufen. Um blockierte Shards zu vermeiden, können Sie die Ereignisquellen-Zuordnung so konfigurieren, dass der Vorgang bei einer kleineren Batch-Größe neu versucht wird, die Anzahl der Neuversuche begrenzt wird oder Datensätze, die zu alt sind, verworfen werden. Um verworfene Ereignisse beizubehalten, können Sie die Ereignisquellen-Zuordnung so konfigurieren, dass Details über fehlgeschlagene Batches an eine Amazon Simple Queue Service (Amazon SQS)-Warteschlange oder an ein Amazon Simple Notification Service (Amazon SNS)-Thema gesendet werden.

Event-Sourcing-Muster in AWS

Amazon S3 speichert alle Ereignisse sämtlicher Microservices dauerhaft und ist die einzige Informationsquelle, wenn es um Debugging, die Wiederherstellung des Anwendungszustands oder die Überprüfung von Anwendungsänderungen geht. Es gibt zwei primäre Gründe, warum Datensätze mehr als einmal an Ihre Kinesis-Data-Streams-Anwendung übermittelt werden: Wiederholungsversuche des Produzenten und Wiederholungsversuche des Konsumenten. Ihre Anwendung muss in der Lage sein, einzelne Datensätze mehrere Male angemessen zu verarbeiten.