Handelt es sich in microservice um eine einzelne Datenbank oder eine einzelne Datenbankinstanz für jeden Dienst?

50

Ich verstehe, dass jeder Dienst in einer Microservice-Architektur eine eigene Datenbank haben sollte. Wenn Sie jedoch eine eigene Datenbank haben, bedeutet dies tatsächlich, dass Sie einfach eine andere Datenbank innerhalb derselben Datenbankinstanz oder wörtlich eine andere Datenbankinstanz haben?

Damit meine ich nicht das Teilen von Datenbanken, was ein Nein-Nein ist, sondern die Datenbankinstanz.

Wenn ich beispielsweise AWS verwendet habe und drei Dienste habe, erstelle ich drei Datenbanken für jeden Dienst auf einer einzelnen RDS-Instanz oder erstelle ich drei RDS-Instanzen mit jeweils einer Datenbank, die von jedem der drei Dienste unabhängig verwendet wird?

Wenn die Verwendung mehrerer Datenbanken auf einer einzelnen RDS-Instanz eine bessere Idee ist, kann dies den Zweck unabhängiger Dienste zunichte machen, da:

  1. Die Ressource der RDS-Instanz wird von den Diensten gemeinsam genutzt. Beeinflusst Service A, der zu einem bestimmten Zeitpunkt möglicherweise eine starke Datenbanknutzung aufweist, Service B, der eine andere Datenbank verwendet, jedoch auf derselben RDS-Instanz?

  2. Alle Dienste sind von der Datenbankversion auf dieser RDS-Instanz abhängig.

Xenon
quelle
8
Es ist das, was Ihren spezifischen Anforderungen am besten entspricht.
Robert Harvey
1
Ich bin mir nicht sicher, ob ich mich als Experte für "Microservices" bezeichnen würde, aber Sie könnten jede Art von Setups und DBS haben. Sie könnten eine Datenbank haben, die von einem Dienst gelesen und von einem anderen geschrieben wird. Oder Sie könnten alternativ nur 1 db (oder weniger technisch) für das gesamte System haben.
Mark Rogers
Hier ist eine gute Lektüre zu diesem Thema: plainoldobjects.com/2015/09/02/…
RandomUs1r
Lesen Sie mehr über das Prinzip der Einzelverantwortung. Haben Sie darüber nachgedacht, einen 'Datenbank-Microservice' zu implementieren, den andere Microservices verwenden?
ChuckCottrill

Antworten:

20

Es hängt wirklich von Ihren Skalierbarkeitsanforderungen ab und davon, wie / ob Ihre Microservice-Instanzen zusammenarbeiten müssen, um ein einziges Ergebnis zu erzielen. Es hilft zu wissen, was die Kompromisse sind:

Alles in einer Datenbank

  • Einfachere Konfiguration
  • Keine Koordination oder Kommunikation mit anderen Instanzen Ihres Dienstes erforderlich
  • Einfacher, Ihren gesamten Datensatz zu entdecken
  • Die Systemleistung wird durch die Datenbankleistung begrenzt

Halten Sie die Datenbanken getrennt

  • Die vollständige Antwort auf eine Anfrage kann auf mehrere Microservice-Instanzen verteilt sein
  • In diesem Fall haben Sie die Kommunikation und die Verhandlung zur Lösung der Anforderung erhöht
  • Umgang mit Daten, wenn Sie diesen Mikrodienstknoten verlieren (selbst wenn die Datenbank noch aktiv ist, können Sie nicht darauf zugreifen, bis ein neuer mit der richtigen Konfiguration wieder verfügbar ist)
  • Erhöhte Konfigurationskomplexität

Was ist das Problem, das Sie lösen?

In einigen Fällen sorgen Sie sich nur um kurzlebige Daten. Wenn die Datenbank ausfällt, ist dies kein großes Problem. In diesen Fällen benötigen Sie möglicherweise nicht einmal eine Datenbank. Behalten Sie einfach alles im Gedächtnis und machen Sie die Dinge blitzschnell. Dies ist die einfachste Lösung, mit der Sie arbeiten können.

In anderen Fällen benötigen Sie die Datenintegrität, aber Ihre Datenbank kann ihre Kapazität basierend auf der Anzahl der vorhandenen Knoten erweitern. In diesem Fall ist wahrscheinlich eine einzige Datenbank mehr als ausreichend, und es ist die richtige Antwort, die Reaktionsfähigkeit unabhängig zu verwalten.

Es gibt eine Reihe von Fällen dazwischen. Beispielsweise verfügen Sie möglicherweise über regional spezifische Datenbanken, sodass Sie für jede Instanz Ihres Dienstes in einer anderen Region eine separate Datenbank haben. Normalerweise funktionieren Sharding-Datenbanken nicht in allen Regionen. Auf diese Weise können Sie die Daten ein wenig lokalisieren und die Koordination selbst steuern.

Lehre und Wirklichkeit

Ich habe eine Reihe von Artikeln über Microservices gelesen und wie modular sie sein sollten. Die Empfehlungen reichen von der Beibehaltung der Front-End-, Microservice- und Datenebene als Ganzes bis zur gemeinsamen Nutzung von Datenbank- und / oder Front-End-Code für alle Instanzen. Normalerweise bietet eine stärkere Isolation die größte Skalierbarkeit, die jedoch mit einer höheren Komplexität einhergeht.

Wenn Ihr Microservice sehr rechenintensiv ist, ist es sinnvoll, die Anzahl dieser Microservices nach Bedarf zu skalieren - die gemeinsame Nutzung der Datenbank oder sogar des Front-End-Codes schadet oder behindert diesen Ansatz nicht.

Die Realität sieht so aus, dass für die spezifischen Anforderungen Ihres Projekts andere Kompromisse erforderlich sind, um die Arbeit rechtzeitig zu erledigen und die von Ihnen gemessene Systemlast (und ein wenig mehr) zu bewältigen. Betrachten Sie das vollständig isolierte Front-End-, Microservice- und Data Tier-Trio als das oberste Ziel. Je mehr Anforderungen an Ihr System gestellt werden, desto näher müssen Sie wahrscheinlich an diesem Ziel sein. Wir sind nicht alle [insert name of highly successful web entity here], und sie haben nicht dort angefangen, wo sie jetzt sind. Manchmal muss man einfach mit einer weniger als perfekten Situation beginnen und damit zufrieden sein.

Berin Loritsch
quelle
71

Angenommen, Sie haben einige Services, die dieselbe Art von DB-System und -Version verwenden können. Wenn Sie unterschiedliche Datenbank- oder DB-Instanzen verwenden, sollten Sie diese Entscheidung nicht zur Entwurfszeit treffen müssen. Stattdessen sollten Sie in der Lage sein, die Entscheidung zur Bereitstellungszeit zu treffen, was Sie einfach konfigurieren können. Entwerfen Sie Ihre Dienste so, dass sie unabhängig von dem Ort sind, an dem die Datenbanken anderer Dienste gehostet werden.

Während des Betriebs können Sie mit einer Instanz beginnen. Wenn das System ordnungsgemäß funktioniert, lassen Sie es so. Wenn Sie jedoch feststellen, dass dies für Ihr System nicht gut skalierbar ist, weil verschiedene Datenbanken auf einer Instanz zu viele Ressourcen gemeinsam nutzen, haben Sie immer die Möglichkeit, verschiedene Instanzen zu verwenden, wenn dies hilfreich ist.

Ein Dienst verletzt also nicht die Microservice-Architektur, nur weil Sie zwei von ihnen eine Ressource teilen lassen - er verletzt sie, wenn die Freigabe der Ressource obligatorisch wird.

Doc Brown
quelle
Dies klingt nach einer vorzeitigen Optimierung. Was ist, wenn die verbrauchten Ressourcen keine zusätzlichen Instanzen verdienen? Dann haben Sie Zeit damit verschwendet, die Flexibilität zu
verbessern
5
@reggaeguitar: Die Kosten hierfür sollten normalerweise vernachlässigbar sein. Bei einer Mikrodienstarchitektur ist es möglicherweise aufwändiger, die Datenbankkonfiguration zwischen verschiedenen Diensten zu zentralisieren, als den Datenbankspeicherort für jeden Dienst einzeln konfigurierbar zu halten. Darüber hinaus ist der springende Punkt einer Microservice-Architektur eine hohe Skalierbarkeit. Wenn man dies nicht benötigt, sollte man sich nicht zuerst für Microservices entscheiden.
Doc Brown
1
@ DocBrown Das macht Sinn, danke für die Antwort!
Reggaeguitar
13

Es spielt keine Rolle.

Das einzige Szenario, in dem es theoretisch von Bedeutung sein könnte, besteht darin, dass ein Dienst auf eine andere Version der Datenbank migriert werden muss. Aber selbst dann gibt es keinen wirklichen Unterschied zwischen dem Vorhandensein separater Instanzen von Anfang an und dem Migrieren dieses einen Dienstes von einer gemeinsam genutzten auf eine separate Instanz. Ich würde sagen, dass separate Instanzen nur aufgrund dieses Szenarios ein Beispiel für YAGNI sind.

Michael Borgwardt
quelle
1
Angenommen, ein bestimmter Dienst wird in einer einzelnen RDS-Instanz stark ausgelastet. Verbraucht er dann die Ressourcen in dieser Instanz und wirkt sich auf die anderen Dienste aus, die dieselbe RDS-Instanz verwenden?
Xenon
1
@xenon: Ja, aber das ist ein Grund zu der Überlegung, die RDS-Leistung durch Tuning, bessere Hardware oder Clustering zu verbessern und nicht Ihre Systemarchitektur zu ändern. Wenn dieser Dienst die Kapazität für die anderen Dienste verlässt, wird ihm bald die Kapazität ausgehen ganz für sich. Obwohl ich vermute, dass Sie besondere Anforderungen haben können, dass ein überlasteter Dienst andere nicht beeinträchtigen darf. Einige RDS erlauben dies in der Tat möglicherweise immer noch in einer einzelnen Instanz, indem sie Ressourcenbeschränkungen auf Benutzerbasis definieren.
Michael Borgwardt
Das Szenario, in dem es darauf ankommt, ist, wenn die Microservice- Instanz einen eigenen Status hat. Dann sollte es mit seiner eigenen Instanz db bereitgestellt werden , was ebenfalls ein Leistungsengpass sein kann
Ewan,
3

Eine RDS-Instanz ist eine einzelne Box. Wenn Sie mehrere Datenbanken auf einer Instanz haben, teilen sie sich die CPU / den Speicher usw.

Wenn die Leistung Ihres Mikrodienstes an die Datenbankleistung gebunden ist , stellen Sie mehrere Kopien des Mikrodienstes bereit, die jeweils eine andere Datenbank verwenden, wobei sich jedoch jede Datenbank auf derselben RDS-Instanz befindet. Ist sinnlos * (außer für Failover). Ihr Microservice-Cluster wird mit der gleichen Geschwindigkeit wie ein einzelner Microservice ausgeführt

Aber ich würde sagen , dass eine Micro , die durch die Datenbankleistung gebunden ist , ist ungewöhnlich.

Normalerweise ruft Ihr Microservice Daten von einer Datenbank ab, führt eine Logik durch und schreibt einige Informationen zurück in die Datenbank. Der Leistungsengpass ist die Logik , nicht das Auswählen und / oder Einfügen.

In diesem Fall können Sie einfach dieselbe Datenbank für alle Ihre Mikroservice-Instanzen freigeben

Ewan
quelle
Ich muss Ihre Behauptung in Frage stellen, dass die Logik der Engpass ist, nicht die Datenbank. Meiner Erfahrung nach liegt der wahrscheinlichste Ort für Leistungsverbesserungen in der Datenbank.
RubberDuck
hmm ja, aber sicher werden diese Leistungsverbesserungen erreicht, indem die Logik aus der Datenbank in den Dienst verschoben wird. Sobald Sie das getan haben, ist DANN Logik der Engpass
Ewan
1
Normalerweise nein. Diese Verbesserungen resultieren aus der Optimierung von Indizes und Abfragen.
RubberDuck
Nun, das würde nach meiner Erfahrung unter den ungewöhnlichen Fall fallen. Nicht, dass es normalerweise keinen Raum für diese Verbesserungen gibt, aber dass die Datenbank nach dem Entfernen von wirklich schlechten Dingen immer noch der begrenzende Faktor ist.
Ewan
1

Das Ziel, eine Datenbank für einen Dienst privat zu halten, ist die Kapselung. Ihr Microservice ist eine Black Box, die andere Dienste im System über eine öffentliche Schnittstelle nutzen.

Es gibt zwei Ebenen, auf denen diese Kapselung funktioniert:

  • Das erste ist logisch, auf Anwendungsebene. Ihr Service besitzt einige Geschäftsobjekte in Ihrem System und muss den Status dieser Objekte beibehalten. Dass eine bestimmte Datenbank diese Geschäftsobjekte unterstützt, ist nur ein Implementierungsdetail. Indem Sie eine separate Datenbank führen, verhindern Sie, dass andere Dienste Backdoor-Zugriff auf Ihre Implementierung haben, und zwingen sie, stattdessen Ihre öffentliche Schnittstelle zu verwenden. Das Ziel dabei ist saubere Architektur und disziplinierte Programmierung. Wo genau sich die Datenbank befindet, ist auf dieser Ebene unerheblich, solange Ihr Dienst über die richtigen Verbindungsdetails verfügt, damit er sie finden kann.

  • Die zweite Ebene ist betriebsbereit. Auch wenn Ihr Entwurf eine perfekte Black Box ist, können, wie Sie betonen, unterschiedliche Arbeiten, die auf einem einzelnen Computer ausgeführt werden, um Ressourcen konkurrieren. Dies ist ein guter Grund, separate logische Datenbanken auf separaten Computern zu platzieren. Wie andere Antworten festgestellt haben, ist dies ein pragmatisches Argument für die Colocation auf einer einzelnen Maschine, wenn Ihre Anforderungen nicht sehr hoch sind und Ihr Budget knapp ist. Jedoch, wie immer, Kompromisse: Dieses Setup erfordert möglicherweise mehr Babysitting, wenn Ihr System wächst. Wenn das Budget es zulässt, bevorzuge ich fast immer zwei separate kleine Maschinen, um zwei Aufgaben auszuführen, anstatt eine größere Maschine gemeinsam zu nutzen.

ben Autor
quelle
1

Ich denke, es könnte hilfreich sein, hier etwas theoretischer vorzugehen. Eine der motivierenden Ideen hinter Microservices ist das Weitergeben von Nachrichten. Ein Microservice ist wie ein Schauspieler im Actor-Modell. Dies bedeutet, dass jeder Prozess seinen eigenen lokalen Status beibehält und der einzige Weg für einen Prozess, auf den Status eines anderen zuzugreifen, das Senden von Nachrichten ist (und selbst dann kann der andere Prozess auf diese Nachrichten reagieren, wie er möchte). Mit "jeder Mikrodienst hat seine eigene Datenbank" ist gemeint, dass der Status eines Prozesses (dh Mikrodienst) lokal und privat ist . Zu einem großen Teil, legt dies nahe , dass die „Datenbank“ sollte kollokiertmit dem Mikrodienst, dh die "Datenbank" sollte auf demselben logischen Knoten wie der Mikrodienst gespeichert und ausgeführt werden. Verschiedene "Instanzen" des Mikrodienstes sind separate Prozesse und sollten daher jeweils eine eigene "Datenbank" haben.

Eine globale Datenbank oder eine Datenbank, die von Mikrodiensten oder sogar Instanzen eines Mikrodienstes gemeinsam genutzt wird, würde aus dieser Perspektive einen gemeinsam genutzten Zustand darstellen. Die "angemessene" Möglichkeit, dies aus der Sicht von Microservices zu handhaben, besteht darin, die gemeinsam genutzte Datenbank durch einen Microservice "Datenbank" vermitteln zu lassen. Andere Mikrodienste, die Informationen zum Inhalt der Datenbank benötigen, senden Nachrichten an diesen "Datenbank-Mikrodienst". Dies beseitigt normalerweise nicht die Notwendigkeit eines lokalen Zustands (dh pro Mikrodienstinstanz "Datenbanken") für die ursprünglichen Mikrodienste! Was sich ändert, ist das, was dieser lokale Zustand darstellt. Anstatt "User Sally ist ein Administrator" zu speichern, wird "Der Datenbank-Microservice sagte," User Sally ist ein Administrator "vor fünf Minuten" gespeichert. Mit anderen Worten, über den Zustand anderer Microservices.

Dies hat den Vorteil, dass jeder Microservice in sich geschlossen ist. Dies macht einen Mikrodienst zu einer atomaren Fehlereinheit. Sie müssen sich (meistens) nicht um einen Mikroservice in einem teilweise funktionsfähigen Zustand kümmern. Natürlich wurde das Problem in das Netzwerk der Mikrodienste verlagert. Ein Mikrodienst kann möglicherweise nicht in der Lage sein, die gewünschte Funktion auszuführen, da er nicht in der Lage ist, andere Mikrodienste zu kontaktieren. Der Vorteil ist jedoch, dass der Mikrodienst in einem genau definierten Zustand ist und möglicherweise einen verschlechterten oder eingeschränkten Dienst anbieten kann, z. Der Nachteil ist, dass es sehr schwierig ist, eine konsistente Momentaufnahme des Systems als Ganzes zu erhalten, und es kann ziemlich viel (unerwünschte) Redundanz und Duplizierung geben.

Der Vorschlag ist natürlich nicht, eine Instanz von Oracle in jeden Docker-Container zu stecken. Erstens benötigt nicht jeder Mikrodienst eine "Datenbank". Einige Prozesse benötigen keinen dauerhaften Status, um ordnungsgemäß zu funktionieren. Beispielsweise benötigt ein Mikrodienst, der zwischen zwei Protokollen übersetzt, keinen dauerhaften Status. Wenn ein persistenter Zustand benötigt wird, ist das Wort "Datenbank" nur ein Wort für "persistenter Zustand". Es kann eine Datei mit JSON drin sein oder eine SQLite - Datenbank oder eine lokal laufende Kopie von Oracle , wenn Sie wollen , oder irgendwelche anderen Mittel lokalDaten dauerhaft speichern. Wenn die "Datenbank" nicht lokal ist, sollte sie aus Sicht von Microservices wie ein separater (Mikro-) Service behandelt werden. Zu diesem Zweck ist es niemals sinnvoll, eine RDS-Instanz als "Datenbank" für einen Mikrodienst zu definieren. Auch hier ist die Perspektive nicht "ein Bündel von Mikrodiensten mit eigenen RDS-Datenbanken", sondern "ein Bündel von Mikrodiensten, die mit RDS-Datenbanken kommunizieren ". Zu diesem Zeitpunkt spielt es keine Rolle, ob die Daten in derselben Datenbankinstanz gespeichert sind oder nicht.

Pragmatisch gesehen erhöht eine Microservices-Architektur die Komplexität enorm . Diese Komplexität ist nur der Preis für eine ernsthafte Behandlung von Teilfehlern. Für viele ist es ein Overkill, der die Vorteile möglicherweise nicht wert ist. Sie sollten sich frei fühlen, Ihr System so zu entwerfen, wie es Ihnen am vorteilhaftesten erscheint. Es besteht die gute Möglichkeit, dass Bedenken hinsichtlich Einfachheit und Effizienz zu Abweichungen von einer reinen Microservices-Architektur führen können. Die Kosten werden durch zusätzliche Kopplung verursacht, die ihre eigene Komplexität mit sich bringt, z. B. unsichtbare Wechselwirkungen zwischen Diensten und Einschränkungen Ihrer Freiheit bei der Bereitstellung und Skalierung nach Ihren Wünschen.

Derek Elkins
quelle
"Da andere Microservices nicht kontaktiert werden können." - Ich dachte, Microservices sollten niemals andere Microservices kontaktieren?
Marc