Es gibt keine eindeutige Lösung, da dies ausschließlich von Ihrem Kontext abhängt - insbesondere davon, in welchen Dimensionen Ihr System skalieren soll und welche tatsächlichen Probleme Sie haben. Ist die Datenbank wirklich Ihr Engpass?
Diese (leider etwas langwierige) Antwort lautet ein bisschen wie "Microservices sind schlecht, Monolithen fürs Leben!", Aber das ist nicht meine Absicht. Mein Punkt ist, dass Microservices und verteilte Datenbanken verschiedene Probleme lösen können, aber nicht ohne eigene Probleme. Um ein starkes Argument für Ihre Architektur zu liefern, müssen Sie nachweisen, dass diese Probleme nicht zutreffen, behoben werden können und dass diese Architektur die beste Wahl für Ihre Geschäftsanforderungen ist.
Verteilte Daten sind schwierig.
Die gleiche Flexibilität, die eine bessere Skalierung ermöglicht, ist die Kehrseite schwächerer Garantien. Insbesondere sind verteilte Systeme viel schwieriger zu beurteilen.
Atomare Aktualisierungen, Transaktionen, Konsistenz / referenzielle Integrität und Beständigkeit sind äußerst wertvoll und sollten nicht vorschnell aufgegeben werden. Es macht wenig Sinn, Daten zu haben, die unvollständig, veraltet oder völlig falsch sind. Wenn Sie ACID als Geschäftsanforderung haben, jedoch eine Datenbanktechnologie verwenden, die dies nicht ohne weiteres bietet (z. B. viele NoSQL-Datenbanken oder eine DB-per-Microservice-Architektur), muss Ihre Anwendung diese Lücke füllen und diese Garantien bieten.
Dies ist nicht unmöglich zu tun, aber schwierig, es richtig zu machen. Sehr trickreich. Besonders in einer verteilten Umgebung, in der es mehrere Writer für jede Datenbank gibt. Diese Schwierigkeit führt zu einer hohen Wahrscheinlichkeit von Fehlern, die möglicherweise verworfene Daten, inkonsistente Daten usw. umfassen.
Lesen Sie beispielsweise die Jepsen-Analysen bekannter verteilter Datenbanksysteme , möglicherweise beginnend mit der Analyse von Cassandra . Ich verstehe die Hälfte dieser Analyse nicht, aber die TL; DR ist, dass verteilte Systeme so schwierig sind, dass selbst branchenführende Projekte sie manchmal in einer Weise falsch verstehen, die im Nachhinein offensichtlich erscheinen kann.
Verteilte Systeme bedeuten auch einen größeren Entwicklungsaufwand. Bis zu einem gewissen Grad besteht ein direkter Kompromiss zwischen den Entwicklungskosten und dem Verlust von Geld für leistungsfähigere Hardware.
Beispiel: baumelnde Referenzen
In der Praxis sollten Sie sich nicht mit Informatik befassen, sondern mit Ihren geschäftlichen Anforderungen, um festzustellen, ob und wie ACID gelockert werden kann. Beispielsweise sind viele Fremdschlüsselbeziehungen möglicherweise nicht so wichtig, wie sie scheinen. Betrachten Sie eine Beziehung zwischen Produkt und Kategorie n: m. In einem RDBMS verwenden wir möglicherweise eine Fremdschlüsseleinschränkung, sodass nur vorhandene Produkte und vorhandene Kategorien Teil dieser Beziehung sein können. Was passiert, wenn wir separate Produkt- und Kategoriedienstleistungen einführen und ein Produkt oder eine Kategorie gelöscht wird?
In diesem Fall ist dies möglicherweise kein großes Problem, und wir können unsere Anwendung so schreiben, dass nicht mehr vorhandene Produkte oder Kategorien herausgefiltert werden. Aber es gibt Kompromisse!
Beachten Sie, dass dies möglicherweise eine Anwendungsebene JOIN
für mehrere Datenbanken / Mikrodienste erfordert , wodurch lediglich die Verarbeitung vom Datenbankserver auf Ihre Anwendung verlagert wird. Dies erhöht die Gesamtlast und muss zusätzliche Daten über das Netzwerk übertragen.
Dies kann mit der Paginierung zu schaffen machen. Sie fordern beispielsweise die nächsten 25 Produkte aus einer Kategorie an und filtern nicht verfügbare Produkte aus dieser Antwort heraus. Jetzt zeigt Ihre Anwendung 23 Produkte an. Theoretisch wäre auch eine Seite mit Nullprodukten möglich!
Sie möchten gelegentlich ein Skript ausführen, mit dem herabhängende Referenzen entweder nach jeder relevanten Änderung oder in regelmäßigen Abständen bereinigt werden. Beachten Sie, dass solche Skripte ziemlich teuer sind, da sie jedes Produkt / jede Kategorie von der Hintergrunddatenbank / dem Mikroservice anfordern müssen, um festzustellen, ob es noch vorhanden ist.
Dies sollte offensichtlich sein, aber aus Gründen der Übersichtlichkeit: Verwenden Sie IDs nicht erneut. Autoincrement-ähnliche IDs sind möglicherweise in Ordnung oder nicht. GUIDs oder Hashes geben Ihnen mehr Flexibilität, z. B. indem Sie eine ID zuweisen können, bevor der Artikel in eine Datenbank eingefügt wird.
Beispiel: gleichzeitige Bestellungen
Betrachten Sie stattdessen eine Beziehung zwischen Produkt und Bestellung. Was passiert mit einer Bestellung, wenn ein Produkt gelöscht oder geändert wird? Ok, wir können einfach die relevanten Produktdaten in den Auftragseingang kopieren, um sie verfügbar zu halten. Aber was ist, wenn sich der Preis des Produkts ändert oder das Produkt nicht mehr verfügbar ist, bevor eine Bestellung für dieses Produkt aufgegeben wird? In einem verteilten System dauert die Verbreitung von Effekten einige Zeit, und die Bestellung wird wahrscheinlich veraltete Daten enthalten.
Wie Sie dies angehen, hängt wiederum von Ihren Geschäftsanforderungen ab. Möglicherweise ist die veraltete Bestellung akzeptabel und Sie können die Bestellung später stornieren, wenn sie nicht erfüllt werden kann.
Aber vielleicht ist das keine Option, z. B. für sehr gleichzeitige Einstellungen. Stellen Sie sich vor, dass 3000 Personen innerhalb der ersten 10 Sekunden Konzertkarten kaufen, und nehmen wir an, dass eine Änderung der Verfügbarkeit 10 ms erfordert, um sich zu verbreiten. Wie hoch ist die Wahrscheinlichkeit, dass das letzte Ticket an mehrere Personen verkauft wird? Hängt davon ab, wie mit diesen Kollisionen umgegangen wird. Bei Verwendung einer Poisson-Verteilung besteht λ = 3000 / (10s / 10ms) = 3
jedoch die P(k > 1) = 1 - P(k = 0) - P(k = 1) = 80%
Möglichkeit einer Kollision pro 10-ms-Intervall. Ob der Verkauf und die spätere Stornierung eines Großteils Ihrer Bestellungen ohne Betrug möglich ist, kann zu einem interessanten Gespräch mit Ihrer Rechtsabteilung führen.
Pragmatismus bedeutet, die besten Eigenschaften herauszusuchen.
Die gute Nachricht ist, dass Sie nicht auf ein verteiltes Datenbankmodell umsteigen müssen, wenn dies nicht anders erforderlich ist. Niemand wird Ihre Mitgliedschaft im Microservice Club kündigen, wenn Sie Microservices nicht „ordnungsgemäß“ durchführen, da es keinen solchen Club gibt - und keine echte Möglichkeit, Microservices aufzubauen.
Pragmatismus gewinnt jedes Mal. Kombinieren Sie verschiedene Ansätze, um Ihr Problem zu lösen. Dies könnte sogar Mikrodienste mit einer zentralisierten Datenbank bedeuten. Machen Sie sich nicht die Qualen verteilter Datenbanken zunutze, wenn Sie das nicht müssen.
Sie können ohne Microservices skalieren.
Microservices haben zwei Hauptvorteile:
- Der organisatorische Vorteil besteht darin, dass sie von separaten Teams unabhängig entwickelt und bereitgestellt werden können (was wiederum erfordert, dass die Dienste eine stabile Schnittstelle bieten).
- Der betriebliche Vorteil, dass jeder Mikrodienst unabhängig skaliert werden kann .
Wenn keine unabhängige Skalierung erforderlich ist, sind Mikrodienste viel weniger attraktiv.
Ein Datenbankserver ist bereits eine Art Dienst, den Sie (etwas) unabhängig skalieren können, z. B. durch Hinzufügen von Leserepliken. Sie erwähnen gespeicherte Prozeduren. Das Reduzieren kann einen so großen Effekt haben, dass andere Skalierbarkeitsdiskussionen umstritten sind.
Und es ist durchaus möglich, einen skalierbaren Monolithen zu haben, der alle Dienste als Bibliotheken enthält. Sie können dann skalieren, indem Sie mehr Instanzen des Monolithen starten, was natürlich voraussetzt, dass jede Instanz zustandslos ist.
Dies funktioniert in der Regel gut, bis der Monolith zu groß ist, um angemessen bereitgestellt zu werden, oder wenn für einige Dienste spezielle Ressourcenanforderungen gelten, sodass Sie sie möglicherweise unabhängig voneinander skalieren möchten. Die Problemdomänen, für die zusätzliche Ressourcen erforderlich sind, enthalten möglicherweise kein separates Datenmodell.
Haben Sie ein starkes Geschäftsmodell?
Sie kennen die Geschäftsanforderungen Ihres Unternehmens und können daher auf der Grundlage einer Analyse ein Argument für eine Datenbank-pro-Mikroservice-Architektur erstellen:
- dass eine bestimmte Skalierung erforderlich ist und diese Architektur der kostengünstigste Ansatz ist, um diese Skalierbarkeit zu erzielen, unter Berücksichtigung des erhöhten Entwicklungsaufwands für eine solche Einrichtung und für alternative Lösungen; und
- dass Ihre geschäftlichen Anforderungen eine Lockerung der relevanten ACID-Garantien ermöglichen, ohne dass dies zu verschiedenen Problemen wie den oben diskutierten führt.
Wenn Sie dies jedoch nicht nachweisen können, insbesondere wenn das aktuelle Datenbankdesign eine ausreichende Skalierung für die Zukunft unterstützt (wie Ihre Kollegen anscheinend glauben), haben Sie auch Ihre Antwort.
Es gibt auch eine große YAGNI-Komponente für die Skalierbarkeit. Angesichts der Unsicherheit ist es eine strategische Geschäftsentscheidung, jetzt auf Skalierbarkeit zu setzen (geringere Gesamtkosten, die jedoch Opportunitätskosten mit sich bringen und möglicherweise nicht erforderlich sind), im Gegensatz zu einer Verschiebung einiger Arbeiten zur Skalierbarkeit (höhere Gesamtkosten, falls erforderlich, aber bessere) Idee des tatsächlichen Maßstabs). Dies ist nicht in erster Linie eine technische Entscheidung.