Mein Team migriert von einer monolithischen ASP.NET-Anwendung auf .NET Core und Kubernetes. Die Codeänderungen scheinen so gut zu verlaufen, wie erwartet, aber wo mein Team auf viel Zwietracht stößt, ist die Datenbank.
Derzeit verfügen wir über eine relativ große SQL Server-Datenbank, in der alle Daten für unser gesamtes Unternehmen gespeichert sind. Ich schlage vor, dass wir die Datenbank auf ähnliche Weise wie den Code aufteilen - Katalogdaten in eine (logische) Datenbank, Inventardaten in eine andere, Bestellungen in eine andere usw. - und jeder Mikrodienst wäre der Gatekeeper für seine Datenbank .
Dies impliziert, dass Fremdschlüssel, die Mikrodienstgrenzen überschreiten, entfernt werden müssten und Sprocs und Ansichten, die über Grenzen hinweg reichen, verboten wären. Alle Datenmodelle können sich in derselben physischen Datenbank befinden oder nicht, aber selbst wenn dies der Fall ist, sollten sie nicht direkt miteinander interagieren. Bestellungen verweisen möglicherweise immer noch auf Katalogelemente nach ID, aber die Datenintegrität wird auf Datenbankebene nicht strikt durchgesetzt, und die Daten müssen in Code und nicht in SQL verknüpft werden.
Ich betrachte den Verlust dieser Funktionen als notwendigen Kompromiss, wenn es darum geht, auf Microservice umzusteigen und die damit verbundenen Vorteile für die Skalierbarkeit zu erzielen. Solange wir unsere Nähte mit Bedacht auswählen und um sie herum entwickeln, sollte es in Ordnung sein. Andere Teammitglieder sind der festen Überzeugung, dass sich alles in derselben monolithischen Datenbank befinden muss, damit alles SÄURE sein und die referenzielle Integrität überall erhalten bleibt.
Das bringt mich zu meiner Frage. Erstens, ist meine Haltung zu Fremdschlüsseleinschränkungen und zum Beitritt plausibel? Wenn ja, ist jemandem glaubwürdiges Lesematerial bekannt, das ich meinen Kollegen anbieten könnte? Ihre Position ist fast religiös und sie scheinen nicht von irgendetwas anderem beeinflusst zu werden, als dass Martin Fowler ihnen sagt, dass sie falsch liegen.
quelle
Antworten:
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 dieP(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:
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:
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.
quelle
Ich halte beide Ansätze für plausibel. Sie können wählen, ob Sie die Skalierbarkeit erhalten möchten, indem Sie die Vorteile von ACID- und monolithischen Datenbanken nutzen, die aktuelle Architektur beibehalten und die Skalierbarkeit und Agilität einer verteilten Architektur aufgeben. Die richtige Entscheidung wird sich aus dem aktuellen Geschäftsmodell und der Buz-Strategie für die nächsten Jahre ergeben. Rein aus technologischer Sicht gibt es Probleme, die es monolithisch halten und zu einem verteilten Ansatz übergehen. Ich würde das System analysieren und herausfinden, welche Anwendungen / Module / Geschäftsprozesse für die Skalierung kritischer sind, und die Risiken, Kosten und Vorteile bewerten, um diejenigen zu bestimmen, die in der monolithischen Architektur warten oder fortfahren sollen.
quelle
Ihre Haltung ist plausibel und richtig.
Eine andere Frage ist jedoch, wie man eingefärbte Db-Süchtige überzeugen kann. Ich würde sagen, Sie haben zwei Möglichkeiten.
Finden Sie ein konkretes Beispiel, an dem die DB an ihre Grenzen stößt. Haben Sie zum Beispiel 'Archivtabellen'? Warum ist das ok Was ist die maximale Anzahl von Bestellungen pro Sekunde, die Sie annehmen können? usw. Zeigen Sie, dass die Datenbank die Anforderungen nicht erfüllt und Ihre Lösung sie behebt.
Stellen Sie teure Vertragspartner ein, um die beste Lösung zu finden. Weil sie teuer sind und Blogs haben, wird ihnen jeder glauben
quelle