Letzte Woche beim CHAR(10) Konferenz hatten wir einen Workshop zum Thema „Cloud-Datenbanken“. Einfach ausgedrückt:Was tun, wenn die Anforderungen des Anwendungsfalls die verfügbaren Ressourcen des Datenbankservers übersteigen.
Dies war ein Hauptthema der gesamten Konferenz, und mehrere Lösungen wurden im Laufe des Tages veranschaulicht. Ein gemeinsames Thema war, dass keine Lösung für alle Anwendungsfälle geeignet ist und dass jede Lösung ihren Preis hat; Daher müssen Sie die Lösung wählen, die sich Ihr Anwendungsfall leisten kann.
Ein weiterer gemeinsamer (wenn auch impliziter) Punkt war der Fokus auf „High-Level“-Lösungen, d. h. das Verbinden mehrerer Datenbankserver auf einer höheren Ebene, um einen einzelnen Server mit größeren Ressourcen zu emulieren.
Ein offensichtlicher Vorteil ist, dass Sie den gut geprüften PostgreSQL-Code nicht ändern müssen; Ein Nachteil besteht darin, dass Sie bei Verwendung mehrerer Datenbankserver mit ihren unabhängigen Zeitachsen einige nützliche Eigenschaften verlieren. Zwei Beispiele:Der teilweise Verlust der Transaktionssemantik erzeugt Konflikte; Das Vorparsen jeder Abfrage außerhalb der Datenbank führt zu Einschränkungen bei den akzeptierten Abfragen.
Die Diskussion war ziemlich interessant, und als Dimitri Fontaine entfernte Tablespaces erwähnte, begann ich, mich über eine verwandte, aber unterschiedliche Idee zu wundern, nämlich:ob ein Ansatz auf niedrigerer Ebene auf das Problem der Zusammenlegung von Ressourcen wäre wirklich unpraktisch. Bevor ich auf die Details eingehen konnte, endete der Workshop, und ich konnte einigen der Leute, die am Whiteboard saßen (darunter Gabriele Bartolini, Nic Ferrier, Marko Kreen, Hannu Krosing, Greg Smith), die Idee zusammen mit den Grundlagen nur skizzieren Fragen "Sieht es machbar aus?" und „entspricht das etwas, das Sie schon kennen?“.
Eine kurze Skizze:So lässt sich ein Applikations-Stack darstellen
(application) --> (connection) --> (db server) --> (resources)
wobei die von der Datenbank verwendeten Ressourcen Speicher, RAM und CPUs umfassen. Der Zweck besteht darin, der Anwendung zu ermöglichen, mehr Ressourcen zu befehlen, um Kapazität und Geschwindigkeit zu erhöhen. „Clevere“ Anwendungen, die mehrere Datenbanken verwalten, können als
dargestellt werden(application) --> (connection) --> (db server) --> (resources) | +---------> (connection) --> (db server) --> (resources)
während „Verbindungspooling“-Lösungen dargestellt werden können als
(application) --> (connection) --> (db server) --> (resources) | +---------> (db server) --> (resources)
Mit „untergeordneten“ Lösungen meine ich so etwas wie
(application) --> (connection) --> (db server) --> (resources) | +---------> (resources)
was etwas Vertrautem ähneln könnte, aber es ist nicht das, was ich hier vorschlage. Um den Unterschied zu erklären, kann ich das Detail vergrößern und schreiben
(resources) = (virtual resources) --> (physical resources)
um die Tatsache darzustellen, dass Sie auf der untersten Ebene eine nicht-triviale Zuordnung zwischen physischen und virtuellen Objekten haben können. Beispielsweise können SAN-Speicher oder RAID-Striping größere virtuelle Laufwerke bereitstellen, indem kleinere physische Laufwerke zusammengefügt werden. Solche Fälle könnte man sich vorstellen als
(application) --> (connection) --> (db server) --> (virt.res.) --> (ph.res.) | +--------> (ph.res.)
Mein Vorschlag ist, Ressourcen auf dem Datenbankserver zu bündeln Ebene, so dass wir eine effizientere „Virtualisierung“ erreichen können, indem wir das Wissen um die spezifischen Anwendungsfälle für jede Ressource (CPU, RAM, Festplatte) nutzen, und gleichzeitig können wir viele der Schwierigkeiten des transaktionalen Paradigmas vermeiden. Das Bild wäre:
(application) --> (connection) --> (db server) --> (virt.res.) --> (ph.res.) | +--------> (virt.res.) --> (ph.res.)
Der Vorteil ist, dass wir nicht alle möglichen Anwendungsfälle für jede virtuelle Ressource verwalten müssen; wir müssen nur die Anwendungsfälle verwalten (und optimieren), die von PostgreSQL tatsächlich benötigt werden. Zum Beispiel:WAL sollte immer noch in lokalen „unvirtualisierten“ Speicher geschrieben werden, der bgwriter greift auf lokale und entfernte Ressourcen (RAM und Festplatte) zu usw.
Einige abschließende Worte zur Zuverlässigkeit. Um richtig zu funktionieren, benötigt das gesamte System jedes Subsystem; Teilausfälle werden nicht verwaltet, da diese Architektur nicht redundant ist. Es ist ein verteiltes System, aber nicht geteilt. Wenn diese Architektur eine kostengünstige und einfache Skalierbarkeit über einen virtuellen Datenbankserver bieten könnte, der funktional einem physischen Server mit größeren Ressourcen entspricht, dann könnte Hochverfügbarkeit auf die standardmäßige Weise erreicht werden, indem zwei identische virtuelle Server in einer Hot-Standby-Konfiguration eingerichtet werden.
Die Netzwerkqualität hat einen großen Einfluss auf die Gesamtleistung; Dieses Design kann nur nützlich sein, wenn Sie eine Reihe von Computern im selben LAN haben, nicht nur aus Geschwindigkeitsgründen, sondern auch, weil ein Netzwerkausfall tatsächlich ein Systemausfall wäre. Trotz dieser Einschränkungen bin ich der Meinung, dass es sehr nützlich wäre, diese Option zu haben.
Dies ist immer noch eine Skizze, die als Referenz für weitere Diskussionen dienen soll. Nächste mögliche Schritte:
- um eine detaillierte Liste der Ressourcen-Anwendungsfälle zu erstellen
- um zu entscheiden, welche Technologien in jedem Anwendungsfall am besten helfen können
- um die tatsächlichen Leistungs-/Entwicklungskosten abzuschätzen