Verteilte Datenbanken

Skalierbar durch Verteilung in MariaDB

| Autor / Redakteur: Franz Aman, Chief Marketing Officer der MariaDB Corporation / Ulrike Ostler

Die modulare Architektur von MariaDB erlaubt es, für unterschiedliche Anforderungen verschiedene Speicher-Engines zu nutzen.
Die modulare Architektur von MariaDB erlaubt es, für unterschiedliche Anforderungen verschiedene Speicher-Engines zu nutzen. (Bild: gemeinfrei, Tim_Tonic / Pixabay)

Datenbankmanagementsysteme profitieren sehr davon, wenn sie in verteilten Umgebungen betrieben werden. Denn sie können die Vorteile der Nebenläufigkeit besonders gut nutzen. Dabei gibt es jedoch erhebliche Unterschiede zwischen transaktionalen und analytischen Arbeitslasten. Hier bieten sich unterschiedliche Technologien an, um sowohl bei der Verfügbarkeit als auch bei der Skalierung optimale Ergebnisse zu erzielen.

Verteilte Umgebungen gelten zwar als komplex, sind aber das Rückgrat der heutigen IT. Die meisten Herausforderungen wie das altbekannte Philosophenproblem sind hinreichend gelöst, der Betrieb verteilter Systeme nimmt immer größere Dimensionen an. Mit der zunehmenden Verbreitung von Cloud-Diensten auch bei kritischen Anwendungen schafft das Rechenzentrum den Perimeter ab, Anwendungen und Daten werden fast grenzenlos verteilt. Eine Technologie, die von der Verteilung in besonderem Maße profitiert, ist die relationale Datenbank. Denn Datenbankmanagementsysteme (DBMS) werden durch Verteilung nicht nur wesentlich besser verfügbar. Sie können die mögliche Nebenläufigkeit der Prozesse in vielen Einsatzszenarien optimal ausnutzen und so die eigene Leistungsfähigkeit deutlich ausweiten. Dabei gibt es allerdings sehr unterschiedliche Ansätze, die jeweils spezifische Vor- und Nachteile aufweisen. Und somit für unterschiedliche Einsatzszenarien geeignet sind.

Die klassische Architektur für verteilte Datenbanken ist die Verbindung primärer und sekundärer Systeme. Dieser Ansatz bildet die Basis fast aller Internet-Angebote: Das primäre System verteilt die Tabellen auf eine beliebige Anzahl sekundärer Server. Schreibzugriffe sind nur auf dem primären Server möglich, Lesezugriffe werden grundsätzlich auf die Sekundären geroutet. Damit wird die Konsistenz der Daten über alle Knoten hinweg sichergestellt. Fallen einzelne sekundäre Server aus, ist das für die Verfügbarkeit des Gesamtsystems kein großes Problem, die Last wird auf die verbleibenden Systeme verteilt. Und da die sekundären Server die Tabellen nicht verändern, spielt die bei Ausfällen übliche Server-Amnesie auch keine Rolle. Ist der Knoten wieder online, bekommt er die Daten vom primären Server neu repliziert. Dieser Ansatz ist besonders dann geeignet, wenn wie bei den meisten Online-Angeboten fast ausschließlich Lesezugriffe auf die Daten erfolgen. Hier skaliert die Datenbank relativ einfach, der operative Aufwand bei der Administration ist überschaubar. Zudem stellt diese Architektur keine besonders hohen Anforderungen an die Anbindung der sekundären Server.

Verteiltes Schreiben mit Sharding

Soll die Datenbank auch skalierbare Schreibzugriffe ermöglichen, wie es zum Beispiel bei einem Shop-System der Fall ist, muss die Datenbank Transaktionen unterstützen. Hierfür bietet sich Sharding an: Sharding ist eine spezielle Version der horizontalen Fragmentierung. Dabei werden die Daten auf mehrere Tabellen verteilt, etwa Kundendaten nach Vertriebsregion. Im Unterschied zur Partitionierung, bei der diese Tabellen in der Regel auf einem Server liegen, verteilen sich die Tabellen beim Sharding auf mehrere Server – die so genannten Shards. Aus Sicht der Anwendung, die auf diese verteilte Datenbank zugreift, sind die Shards transparent.

Deutlich wird dies am Beispiel des Open-Source-DBMS MariaDB: Sharding ist hier als Speicher-Engine implementiert – die modulare Architektur von MariaDB erlaubt es, für unterschiedliche Anforderungen verschiedene Speicher-Engines zu nutzen. Im Falle von Sharding kommt die Engine Spider zum Einsatz. Ein Knoten mit Spider-Engines übernimmt dabei Quasi die Rolle des Masters und steuert die Kommunikation zur Anwendung auf der einen und zu den Shards auf der anderen Seite. Für die Anwendung erscheint die verteilte Datenbank als ein normaler MariaDB-Server.

Um Konsistenzprobleme bei den Schreibzugriffen zu verhindern, nutzt das Sharding mit Spider Transaktionen mit Zwei-Wege-Commit. Transaktionen eignen sich grundsätzlich gut für verteilte Systeme, da sie ACID-Eigenschaften aufweisen und so Probleme mit der Datenkonsistenz umgehen:

  • Atomicity (Atomarität): Entweder werden alle Operationen der Transaktion ausgeführt oder keine. Entsprechend gibt es nur zwei Ergebnisse, den Commit im Falle einer erfolgreichen Transaktion oder den Abort bei einem Fehler.
  • Consistency (Konsistenz): Durch die Transaktion wird das System von einem konsistenten Zustand in einen anderen, ebenfalls konsistenten Zustand überführt. Eventuell auftretende Zwischenstufen sind transparent.
  • Isolation (Abgrenzung): Eine Transaktion, die noch nicht erfolgreich abgeschlossen werden konnte, übergibt keine Ergebnisse an eine andere Transaktion. Alle Transaktionen sind nebenläufig.
  • Durability (Dauerhaftigkeit): Sobald eine Transaktion mit einem Commit abgeschlossen wurde, haben die Ergebnisse der Transaktion auch im Falle eines darauffolgenden Fehlers Bestand.

Bei verteilten Datenbanken reicht ein einfacher Commit nicht, da die Transaktion auf mehreren Systemen durchgeführt wird. Hierfür ist der Zwei-Wege-Commit üblich, wie er zum Beispiel in der Spezifikation XA für verteilte Transaktionen auf Basis der Vorschläge der OpenGroup definiert ist.

DBMS als Transaktionsmanager

Bei XA-Transaktionen wird die globale Transaktion zunächst in lokale Transaktionen zerlegt. Jeder Ressource – üblicherweise ist jedes Shard eine solche – wird eine dieser lokalen Transaktionen zugeordnet. Die Verwaltung übernimmt dabei der Transaction Manager, in der Regel das DBMS. Der Commit findet in zwei Stufen statt:

  • 1. Beim ersten Commit fordert der Transaction Manager von den Ressourcen einen Commit für die lokale Transaktion an. Änderungen werden dabei nicht umgesetzt und in die Tabelle geschrieben.
  • 2. Bestätigen alle Ressourcen eine erfolgreiche lokale Transaktion, fordert der Transaction Manager zum zweiten Commit auf. Erst dieser macht die Änderung an den Daten wirksam.

Bestätigt eine Ressource den ersten Commit nicht, gilt die globale Transaktion als fehlgeschlagen und wird zurückgerollt.

Ganz anders stellt sich die Situation dar, wenn nichttransaktionale Arbeitslasten verarbeitet werden müssen. Dabei handelt es sich fast immer um Analysen und Big-Data-Szenarien. Grundsätzlich greifen Transaktionen auf Zeilen zu, also zum Beispiel die Kundendaten mit Name, Anschrift und Kreditkartennummer. Business-Intelligence-Analysen hingegen basieren in der Regel auf aggregierten Daten einer oder mehrerer Spalten. Das können etwa die Durchschnittspreise eines Produkts oder die verkauften Stückzahlen über einen bestimmten Zeitraum sein. Hier braucht weder der Lesezugriff auf eine große Anwendermasse skalieren, noch müssen Daten in der Tabelle fortlaufend verändert werden. Gefordert ist bei analytischen Lasten zunächst, dass die Spalten schnell gelesen werden können und dass sich extrem viele Daten speichern und verarbeiten lassen. Die Verteilung der Datenbank soll also die Leistungsfähigkeit und die Gesamtspeicherkapazität erhöhen.

Kolumnare Speicherung

Dabei ist es zunächst hilfreich, wenn das Datenmodell nicht wie üblich zeilenbasiert ist, sondern sich auf Spalten konzentriert. Bei MariaDB etwa ist das mit der Speicher-Engine ColumnStore möglich. An der Spitze steht dabei ein MariaDB-Server mit einer ColumnStore-Schnittstelle, das so genannte User Module (UM). Dieser kommuniziert mit der Anwendung und verwaltet gleichzeitig die Speicherknoten, die mit der ColumnStore-Engine bestückt sind. Diese werden als Performance Modules (PM) bezeichnet. Die PM sind für die Anwendung transparent. Üblicherweise speichert jeder Knoten einen Teil der gesamten Tabelle, wobei die Aufteilung ganz traditionell nach Zeilen geschieht: Knoten 1 speichert die Zeilen 1 bis 100.000, Knoten 2 die Zeilen 100.001 bis 200.000 und so fort. Der verfügbare Speicherplatz kann dadurch beliebig skalieren, indem weitere Speicherknoten hinzugefügt werden. Und da die Abfragen spaltenbezogen sind, können alle PM parallel abgefragt werden, was erhebliche Geschwindigkeitsvorteile gibt. Zudem lassen sich auf Multi-Core-Systemen die Abfragen in Tasks unterteilen, die auf dem jeweiligen PM parallel ausgeführt werden. Besonders in diesem Szenario spielt eine verteilte Architektur also ihr Potenzial voll aus.

In vielen Einsatzfällen wird es allerdings kaum möglich sein, die Arbeitslasten und Szenarien exakt voneinander abzugrenzen. Vor allem moderne, an die Kunden gerichtete Anwendungen benötigen sowohl hochskalierende Lesezugriffe, sichere Transaktionen und eine Fülle historischer Daten. Hier kann es sinnvoll sein, die verteilte Datenbanklandschaft zu flexibilisieren, etwa durch den Einsatz eines Proxies. Damit steigt zwar häufig die Komplexität der Architektur, dafür sind spezielle Datenbank-Proxies wie MariaDB MaxScale für die darüber liegende Anwendungsschicht völlig transparent: Die Datenbankarchitektur wird komplett von den Anwendungen entkoppelt, die Applikationen sehen in jedem Fall nur einen normalen Datenbank-Server. Welche Technologien und Methoden bei der Verteilung der Datenbanken zum Einsatz kommt, ist aus Anwendungssicht unerheblich. Damit können Änderungen an den Datenbanken vorgenommen werden, ohne dass Anpassungen auf der Anwendungsseite notwendig sind.

Konsolidierte Arbeitslasten

Damit eignet sich dieser Ansatz sehr gut, um unterschiedliche Arbeitslasten zu konsolidieren. MariaDB bietet eine entsprechende Lösung unter dem Namen Platform X3 an. Hier werden unterschiedliche Datenbankansätze zu einem transparenten System zusammengefasst. Auf der einen Seite besteht die Lösung aus einer transaktionsoptimierten Datenbank (OLTP, Online Transaction Processing), die dem oben skizzierten Ansatz mit der Spider-Engine folgt, aber auch mit anderen transaktionalen Speicher-Engines arbeitet. Daneben umfasst die Platform eine Datenbank für analytische Arbeitslasten (OLAP, Online Analytical Processing) nach dem kolumnaren Ansatz. Zusammengefasst werden beide Datenbankwelten durch den Proxy, der unter anderem als Router fungiert und die Anfragen je nach transaktionalem oder analytischem Inhalt an die jeweilige Instanz leitet.

Verteilte Architekturen sind bei Datenbanken als eine Variante des Scale-Out-Ansatzes fast unverzichtbar, um die geforderte Leistungsfähigkeit und Speicherkapazität zu erzielen. Je nach Arbeitslast sind andere Fähigkeiten und Optimierungen gefragt, denen bei der Architektur Rechnung getragen werden sollte. Die Praxis zeigt: Ein „one size fits all“-Ansatz funktioniert nur für kleinere Datenmengen und einer geringen Anzahl von Abfragen. Sobald Datenbanken skalieren müssen, etwa weil sich die Geschäfte des Unternehmens sehr gut entwickeln, kommen nicht-optimierte Lösungen schnell an ihre Grenzen – entweder bei Transaktionen oder bei Analysen.

Was meinen Sie zu diesem Thema?

Schreiben Sie uns hier Ihre Meinung ...
(nicht registrierter User)

Zur Wahrung unserer Interessen speichern wir zusätzlich zu den o.g. Informationen die IP-Adresse. Dies dient ausschließlich dem Zweck, dass Sie als Urheber des Kommentars identifiziert werden können. Rechtliche Grundlage ist die Wahrung berechtigter Interessen gem. Art 6 Abs 1 lit. f) DSGVO.
Kommentar abschicken
copyright

Dieser Beitrag ist urheberrechtlich geschützt. Sie wollen ihn für Ihre Zwecke verwenden? Infos finden Sie unter www.mycontentfactory.de (ID: 45840493 / RZ-Tools)