Der Wechsel von einem monolithischen zu einem Microservices-Architekturmodell bietet zahlreiche Vorteile, die besonders in dynamischen und skalierungsorientierten Unternehmensumgebungen wichtig sind. Doch wie geht man dabei eigentlich mit den Daten um?
Oder anders: Dieser Artikel beschreibt eine Schritt-für-Schritt-Anleitung für die Migration der Daten von einem Monolithen zu einer Microservice-Architektur.
Warum Microservices?
Nun, dieser Ansatz ermöglicht eine bessere Skalierbarkeit einzelner Komponenten. Da Microservices unabhängig voneinander skalierbar sind, können die am meisten beanspruchten Teile einer Anwendung flexibel und effizient hoch- oder runterskaliert werden, ohne die gesamte Anwendung beeinflussen zu müssen.
Die Microservices-Architektur verbessert die Resilienz des Systems; eine Störung in einem Service hat nicht zwangsläufig Auswirkungen auf andere Services. Der Ansatz fördert eine schnellere Markteinführung neuer Features, da Teams einzelne Services unabhängig entwickeln und deployen können, was eben zu einer beschleunigten Innovationsrate führt. Außerdem unterstützt die Dezentralisierung durch Microservices eine vielfältige Auswahl von Technologien, Programmiersprachen und Datenbanksystemen, sodass jedes Team die am besten geeigneten Tools für seine spezifischen Anforderungen wählen kann.
Schließlich erleichtert die Aufteilung in kleinere, überschaubare Komponenten das Verständnis und die Wartung des Codes. Langfristig führt das zu einer höheren Codequalität und es senkt die Wartungskosten.
Datenmigration – von Monolith zu Microservices
Bevor man anfängt, sollte man natürlich wissen, was genau man denn aus dem Monolithen herauslösen möchte. Dieses Datenaggregat wäre dann auch namensgebend für den neuen Microservice. Beispiele hierfür wären Kundendaten, Rechnungen, Produkte, Bezahldaten, etc.
Der erste Schritt: Ein Proxy-Service für den Monolithen
An erster Stelle steht die Schaffung eines Microservices, in den der Code für die relevanten Datenbankzugriffe aus dem Monolithen dupliziert wird. Damit kann nun der neue Service die ursprüngliche Aufgabe übernehmen. Es wird allerdings zunächst immer noch dieselbe Datenbank – die Datenbank des Monolithen – dafür verwendet. Mit diesem Vorgehen hat man den Grundstein gelegt.
Man kann nun damit beginnen, sowohl andere Services als auch den Monolithen selbst schrittweise auf diesen neuen Service umzustellen. Statt direkt auf seine eigene Datenbank zuzugreifen, nutzt der Monolith nun den Service als Proxy.
Datenbanken aufteilen: Welche Daten gehören dem Microservice?
Die eigentliche Herausforderung beginnt jedoch mit der Frage, welche Daten nun dem neuen Microservice gehören. Welche Daten gehören logisch zu diesem Service, und welche müssen von anderen Services angefragt werden? Schlussendlich muss jeder Service die Single Source of Truth über seine eigenen Daten sein.
Hat man diese Daten identifiziert, geht es daran, für den Microservice eine eigene Datenbank anzulegen und die Daten aus der Monolith-Datenbank in sie zu replizieren. Hierbei ist es essenziell, die Synchronität der Daten in beiden Datenbanken sicherzustellen: neue Daten müssen in beide Systeme geschrieben werden.
Die Umschaltung: Von der Monolith-Datenbank zum eigenen Microservice
Wenn die Synchronisation der Daten in beiden Datenbanken gewährleistet ist, kann der Microservice schließlich auf seine eigene Datenbank umgeschaltet werden. Die ursprüngliche Datenbank des Monolithen dient von nun an lediglich als Backup.
Nachdem nun die vollständige Umstellung auf den neuen Microservice erfolgt und sichergestellt ist, kann schlussendlich der Code für die Synchronisierung der beiden Datenquellen zurückgebaut und die Daten aus der Datenbank des Monolithen entfernt werden.
Aufgemerkt bei Foreign Keys und Transaktionen
Monolithische Datenbanken haben auch ihre Vorteile: Konzepte wie Foreign Keys und Transaktionen werden oft als selbstverständlich angenommen. Sind die Daten aber voneinander getrennt, gehen sie in der Regel verloren.
Beim Löschen von Daten ist ein Soft-Delete-Ansatz häufig die einfachste Lösung: Datensätze werden lediglich als „gelöscht“ markiert, sodass sie gegebenenfalls immer noch auffindbar sind. Falls dies (beispielsweise aufgrund der Datenmenge) nicht möglich ist, sollte man beim Design abhängiger Services darauf achten, dass sie mit fehlenden Datensätzen umgehen können. Will man jedoch den Löschvorgang eines Datensatzes verhindern – weil es noch Daten gibt, die Bezug auf ihn nehmen – bleibt oft nichts anderes übrig, als den Löschvorgang als eine koordinierte Saga abzubilden.
Koordinierte Sagas sind ein Konzept, welches in gewisser Weise einer Transaktion entspricht: Jeder der teilnehmenden Services erhält ein Event, führt seine Operationen aus und signalisiert Erfolg oder Fehler. Die Verantwortung liegt dann bei den vorherigen oder nachfolgenden Services auf diese Events zu reagieren und gegebenenfalls Rollbacks durchzuführen.
Die Herausforderungen der Migration verstehen und meistern
Die Migration von einer monolithischen Architektur zu Microservices stellt zweifellos eine komplexe Herausforderung dar, die eine gründliche Planung und strategische Ausführung erfordert.
Entwicklerteams müssen nicht nur die technischen Aspekte des Wechsels verstehen, sondern auch Bereitschaft zur Anpassung an neue Arbeitsmethoden zeigen. Doch mit der richtigen Herangehensweise, die eine schrittweise und gut überwachte Migration einschließt, lassen sich potenzielle Risiken minimieren und der Übergang erleichtern.
Letztendlich können Teams, die diesen Übergang sorgfältig planen und durchführen, die langfristigen Vorteile einer flexibleren, skalierbareren und resilienteren Anwendung voll ausschöpfen.
Schreibe einen Kommentar