Relationale Datenbanken neu gedacht

Amazon Aurora: Wie wir eine Cloud-native relationale Datenbank entwickelt haben

Werner Vogels

© Shutterstock / MU YEE TING

 

Wie gut sind relationale Datenbanken für Cloud-Anwendungen geeignet? Hervorragend, meint Amazon CTO Werner Vogels, und stellt in diesem Artikel den Datenbank-Dienst Amazon Aurora vor, der das relationale Modell ins Cloud-native-Zeitalter befördern will. Was steckt dahinter?

Wie wir eine Cloud-native relationale Datenbank entwickelt haben

Relationale Datenbanken gibt es schon lange. Das Datenbankmodell wurde bereits in den 70er Jahren von E.F. Codd erstmals beschrieben. Die Kerntechnologien, die den heutigen großen relationalen Datenbankmanagementsystemen zugrundeliegen, gehen auf Entwicklungen in den 80er und 90er Jahren zurück. Die Grundlagen der relationalen Datenbank, einschließlich Datenbeziehungen, ACID-Konzept (Atomicity, Consistency, Isolation, Durability) und SQL-Abfragesprache, haben sich seit jeher bewährt. In Summe haben sie dazu beigetragen, dass relationale Datenbanken heute bei Anwendern in vielen Bereichen sehr beliebt sind. Sie bleiben in vielen Unternehmen ein Eckpfeiler der IT-Infrastruktur.

Das soll nicht heißen, dass der Umgang mit relationalen Datenbanken für einen Systemadministrator unkompliziert ist. Seit Jahrzehnten ist die Verwaltung einer relationalen Datenbank eine arbeitsintensive Aufgabe, die nur hoch qualifiziertes Personal erledigen kann. Die Skalierung einer relationalen Datenbank unter Beibehaltung von Fehlertoleranz, Leistung und „Sprengradiusgröße“ – also die Auswirkungen eines Fehlers – war für Administratoren eine ständige Herausforderung.

Gleichzeitig sind die Anforderungen an moderne Internet-Workloads gestiegen und erfordern neue zentrale Eigenschaften der Infrastruktur:

  • Benutzer wollen mit einem kleinen Footprint beginnen und dann massiv wachsen, ohne dass die Infrastruktur ihre Geschwindigkeit einschränkt.
  • In großen Systemen sind einzelne Ausfälle eher die Norm und keine Ausnahme. Kunden-Workloads müssen deshalb von Komponentenausfällen oder Systemausfällen isoliert werden.
  • Kleiner Sprengradius: Ein einzelner Systemausfall soll keinen großen Einfluss auf das Unternehmen haben.

Dabei handelt es sich um ernsthafte Probleme, deren Lösung eine Abkehr von den relationalen Datenbankarchitekturen herkömmlicher Art erfordert. Als Amazon mit den Einschränkungen alter relationaler Datenbanken konfrontiert wurde, hat das Unternehmen einen modernen relationalen Datenbankdienst namens Amazon Aurora entwickelt.

Das Design von Aurora bewahrt die zentralen Stärken der transaktionalen Konsistenz von relationalen Datenbanken. Innovationen betreffen vor allem die Speicherschicht. Schließlich ging es darum, ein Datenbanksystem für die Cloud zu entwickeln, das moderne Workloads unterstützt, ohne die Leistung zu beeinträchtigen. Seit der ursprünglichen Veröffentlichung von Aurora gehört die Lösung zu den am schnellsten wachsenden Services in der Geschichte von AWS.

Relationale Datenbanken neu gedacht

Eine klassische Datenbankarchitektur ist folgendermaßen aufgebaut:

Dieser monolithische relationale Datenbank-Stack hat sich in den vergangenen 30 bis 40 Jahren nicht wesentlich verändert. Während verschiedene konventionelle Ansätze zur Skalierung von Datenbanken existieren (etwa Sharding, Shared Nothing oder Shared Disk), teilen sich alle die gleiche grundlegende Datenbankarchitektur. Keiner davon löst die Performance-, Elastizitäts- und Sprengradiusprobleme, da die grundlegende Einschränkung des eng gekoppelten, monolithischen Stacks erhalten bleibt.

Um die Grenzen relationaler Datenbanken zu überwinden, haben wir den Stack neu konzipiert. Dazu wurde das System in seine grundlegenden Bausteine zerlegt. Insbesondere die Cache- und Logging-Schichten waren gute Ansatzpunkte für Innovationen. Wir konnten diese Schichten in einen speziell entwickelten, skalierbaren, selbstheilenden, mandantenfähigen, datenbankoptimierten Speicherdienst überführen. Mit dem Aufbau des verteilten Speichersystems wurde dann Amazon Aurora geboren.

Dabei haben wir die herkömmlichen Ideen des Cachings und Loggens in einer relationalen Datenbank in Frage gestellt, die Datenbank-I/O-Schicht neu aufgesetzt und dadurch große Vorteile bei Skalierbarkeit und Ausfallsicherheit erzielt. Amazon Aurora ist sehr skalierbar und belastbar, weil es die Ideen des Entladens von Redo-Logging, zellbasierter Architektur, Quoren und schneller Datenbankreparaturen aufgreift.

Blockchain Whitepaper 2018

Free: Blockchain Technology Whitepaper

If building a blockchain from scratch is beyond your current scope, the blockchain technology whitepaper is worth a look. Experts from the field share their know-how, tips and tricks, development advice, and strategy for becoming a blockchain master.

Entlastung der Redo-Logging-Funktion: Das Protokoll ist die Datenbank

Traditionelle relationale Datenbanken organisieren Daten in Seiten (pages). Wenn diese geändert werden, müssen sie auf die Festplatte geschrieben werden. Für die Resilienz gegen Fehler und die Wahrung der ACID-Semantik werden Seitenänderungen auch in Redo-Log-Sätzen aufgezeichnet, die in einem kontinuierlichen Stream auf die Festplatte geschrieben werden. Eine solche Architektur bietet zwar die grundlegende Funktionalität, die zur Unterstützung eines relationalen Datenbankmanagementsystems erforderlich ist. Sie ist aber mit einer Vielzahl von Ineffizienzen behaftet. So führt beispielsweise ein einzelner Speichervorgang einer logischen Datenbank zu mehreren (bis zu fünf) physischen Plattenschreibern. Das führt zu Performance-Problemen.

Datenbankadministratoren versuchen, dieses Problem der „Schreibverstärkung“ zu lösen, indem sie die Häufigkeit von Page Flushes reduzieren. Das wiederum verschlimmert das Problem der Crash-Recovery-Dauer. Ein längeres Intervall zwischen den Flushes bedeutet mehr Redo-Log-Sätze, die von der Festplatte gelesen werden müssen, um das richtige Page-Bild zu rekonstruieren. Dies führt zu einer langsameren Erholung.

In Amazon Aurora ist das Protokoll die Datenbank. Datenbankinstanzen schreiben Redo-Log-Sätze auf die verteilte Speicherschicht, und der Speicher kümmert sich bei Bedarf um den Aufbau von Page-Bildern aus Log-Sätzen. Datenbankinstanzen müssen niemals „dirty pages“ bereinigen, da die Speicherschicht immer weiß, wie Pages aussehen. Das verbessert mehrere Aspekte der Performance und Zuverlässigkeit der Datenbanken. Die Schreibleistung wird durch den Wegfall der Schreibverstärkung und den Einsatz einer Scale-Out-Speicherflotte deutlich verbessert.

So liefert die Amazon Aurora MySQL-kompatible Edition etwa die fünffache Schreib-IOPS beim SysBench Benchmark im Vergleich zu Amazon RDS for MySQL, das auf ähnlicher Hardware läuft. Die Zeit für die Wiederherstellung von Datenbankabstürzen wird drastisch verkürzt, da eine Datenbankinstanz keine Wiederholung des Redo-Log-Streams mehr durchführen muss. Die Speicherschicht kümmert sich um die Redo-Log-Anwendung beim Lesen von Seiten. Das führt zu einem neuen Speicherservice, der frei von den Einschränkungen einer älteren Datenbankarchitektur ist.

Zellbasierte Architektur

Wie bereits beschrieben: Ausfälle lassen sich gerade in großen IT-Umgebungen nicht vermeiden. Ganze Instanzen schlagen fehl, und Netzwerkausfälle können erhebliche Teile der Infrastruktur isolieren. Seltener ist ein ganzes Rechenzentrum vom Netz abgehängt oder fällt aufgrund einer Naturkatastrophe aus. Bei AWS entwickeln wir für Ausfallszenarien und verlassen uns dabei auf eine zellbasierte Architektur. So bekämpfen wir Probleme, bevor sie auftreten.

AWS hat mehr als 20 geografische Regionen und innerhalb jeder von ihnen existieren mehrere Verfügbarkeitszonen. Die Nutzung mehrerer Regionen und Zonen ermöglicht es, sowohl Ausfälle von Standardkomponenten als auch größere Katastrophen zu überstehen, ohne die Verfügbarkeit der Dienste zu beeinträchtigen. Amazon Aurora repliziert alle Schreibvorgänge in drei Zonen, um eine hohe Datenbeständigkeit und Verfügbarkeit zu gewährleisten. Tatsächlich kann Aurora den Verlust einer ganzen Zone tolerieren, ohne die Datenverfügbarkeit zu verlieren, und sich nach größeren Ausfällen schnell erholen.

Die Replikation ist jedoch bekanntermaßen Ressourcen-intensiv. Das wirft die Frage auf, wodurch Aurora eine robuste Datenreplikation bei gleichzeitig hoher Leistung bieten kann. Die Antwort liegt in Quoren.

Die Schönheit der Quoren

Ausfälle kommen permanent vor. Je größer das System, desto größer ist die Wahrscheinlichkeit, dass irgendetwas kaputt geht: eine Netzwerkverbindung, eine SSD, eine ganze Instanz oder eine Softwarekomponente. Selbst wenn eine Softwarekomponente fehlerfrei ist, muss sie bei Upgrades regelmäßig neu gestartet werden.

Die traditionellen Ansätze, die I/O-Verarbeitung zu blockieren, bis ein Failover durchgeführt werden kann, und im „degraded mode“ zu arbeiten, wenn eine fehlerhafte Komponente vorhanden ist, schaffen viele Probleme – besonders in skalierten Umgebungen. Anwendungen tolerieren I/O-Schwierigkeiten oft nicht gut. Mit Hilfe einer mäßig komplexen statistischen Berechnung kann gezeigt werden, dass in einem großen System die Wahrscheinlichkeit, im degradierten Modus zu arbeiten, mit zunehmender Systemgröße auf 100 Prozent steigt. Und dann ist da noch das heimtückische Problem der „grauen Fehler“. Sie entstehen, wenn Komponenten nicht vollständig ausfallen, sondern langsam werden. Falls das Systemdesign eine solche Verzögerung nicht vorwegnimmt, kann das die Leistung des Gesamtsystems beeinträchtigen.

Amazon Aurora verwendet Quoren, um die Probleme von Komponentenausfällen und Leistungseinbußen zu bekämpfen. Die Grundidee eines Schreibquorums ist einfach: Das System schreibt so viele Replikate wie möglich, um sicherzustellen, dass ein gelesenes Quorum immer die neuesten Daten findet. Das grundlegendste Quorum-Beispiel ist „2 von 3″:

Vw+Vr > V
Vw > V / 2
V=3
Vw=Vr=2

Beispielsweise könnte das System drei physische Schreibvorgänge mit einem Schreibquorum von 2 durchführen müssen. Es muss nun nicht warten, bis alle drei abgeschlossen sind, bevor der logische Schreibvorgang für erfolgreich erklärt wird. Es ist in Ordnung, wenn ein Schreibvorgang fehlschlägt oder langsam ist, da das gesamte Operationsergebnis und die Latenzzeit nicht durch den Ausreißer beeinflusst werden. Das bringt sehr große Vorteile: Der Schreibvorgang ist erfolgreich und schnell, auch wenn etwas kaputt geht.

Das einfache 2/3 Quorum ermöglicht es, den Verlust einer gesamten Verfügbarkeitszone zu tolerieren. Das ist aber immer noch nicht gut genug. Ein Verlust einer Zone ist zwar ein seltenes Ereignis, macht aber Komponentenausfälle in anderen Zonen nicht weniger wahrscheinlich. Bei der Entwicklung von Aurora war das Ziel die „Verfügbarkeitszone+1“: Wir wollen den Verlust einer Zone plus einen weiteren Ausfall ohne Datenverlust und mit minimalen Auswirkungen auf die Datenverfügbarkeit tolerieren können. Dazu verwenden wir ein 4/6 Quorum:

Vw+Vr > V
Vw > V / 2
V=6
Vw=4
Vr=3

Für jedes Schreiben von logischen Protokollen geben wir sechs physische Replikatschreibvorgänge aus und betrachten den Schreibvorgang als erfolgreich, wenn vier davon abgeschlossen sind. Mit zwei Replikaten pro Zone, wenn eine gesamte Verfügbarkeitszone ausfällt, wird ein Schreiben noch abgeschlossen. Wenn eine Zone ausfällt und ein zusätzlicher Fehler auftritt, können Sie immer noch das Read Quorum erreichen und dann durch eine schnelle Reparatur wieder die Schreibfähigkeit erlangen.

Schnelle Reparaturen und Catchups

Es gibt verschiedene Möglichkeiten, die Datenreplikation durchzuführen. In herkömmlichen Speichersystemen erfolgt die Datenspiegelung oder Löschkodierung auf der Ebene einer gesamten physischen Speichereinheit, wobei mehrere Einheiten in einem RAID-Array kombiniert werden. Dieser Ansatz führt dazu, dass Reparaturen lange dauern. Die Leistung des RAID-Arrays ist durch die Fähigkeiten der wenigen Geräte im Array eingeschränkt. Mit zunehmender Größe des Storages steigt auch die Datenmenge, die bei einem Neuaufbau kopiert werden muss.

Amazon Aurora verfolgt bei der Replikation einen völlig anderen Ansatz, der auf Sharding und Scale-Out-Architektur basiert. Ein Aurora-Datenbankvolumen wird logisch in 10-GiB-Logikeinheiten (Protection Groups) unterteilt, und jede Protection Group wird auf sechs Arten in physische Einheiten (Segmente) repliziert. Die einzelnen Segmente sind auf eine große verteilte Storage Fleet verteilt. Wenn ein Fehler auftritt und ein Segment herausfällt, müssen für die Reparatur einer einzelnen Schutzgruppe nur ~10 GiB Daten bewegt werden, was in Sekundenschnelle erfolgt.

Darüber hinaus nimmt bei der Reparatur mehrerer Schutzgruppen die gesamte Storage-Infrastruktur am Reparaturprozess teil. Durch die damit sehr hohe Bandbreite kann der gesamte Reparaturprozess schnell abgeschlossen werden. Im Falle eines Zonenausfalls, gefolgt von einem weiteren Komponentenausfall, kann Aurora also für einige Sekunden das Schreibquorum für eine bestimmte Schutzgruppe verlieren. Eine automatisch eingeleitete Reparatur stellt jedoch die Beschreibbarkeit mit hoher Geschwindigkeit wieder her. Mit anderen Worten, Aurora Storage heilt sich schnell von selbst.

Wie ist es möglich, Daten sechsfach zu replizieren und eine hohe Schreibleistung zu gewährleisten? Dies wäre in einer traditionellen Datenbankarchitektur, in der ganze Seiten oder Festplattensektoren in den Speicher geschrieben werden, nicht möglich, da das Netzwerk überlastet wäre. Im Gegensatz dazu schreiben Instanzen mit Aurora nur Redo-Log-Sätze auf den Speicher. Diese Datensätze sind viel kleiner – typischerweise  zehn bis einige hundert Bytes. Das ermöglicht ein 4/6 Schreibquorum, ohne das Netzwerk zu überlasten.

Die Grundidee eines Schreibquorums impliziert, dass einige Segmente möglicherweise nicht immer und überall alle Schreibvorgänge erhalten. Wie gehen diese Segmente mit Lücken im Redo-Log-Stream um? Aurora-Speicherknoten kommunizieren ständig miteinander, um Löcher zu füllen (und Reparaturen durchzuführen). Der Fortschritt des Protokollstroms wird durch die Verwaltung der Log-Sequenznummer (LSN) eng koordiniert. Wir verwenden einen Satz von LSN-Markern, um den Zustand jedes einzelnen Segments aufrechtzuerhalten.

Wie sehen Lesevorgänge aus? Ein Lesevorgang des Quorums ist teuer und sollte am besten vermieden werden. Der Client-seitige Aurora-Speicher-Treiber kann nachvollziehen, welche Schreibvorgänge für welches Segment erfolgreich waren. Es muss kein Quorum-Lesevorgang für routinemäßige Seitenlesungen erfolgen, da stets bekannt ist, wo eine aktuelle Kopie einer Seite erhältlich ist. Darüber hinaus verfolgt der Treiber Latenzen und versucht immer, von dem Speicherknoten zu lesen, der die niedrigste Latenz in der Vergangenheit aufgewiesen hat. Das einzige Szenario, in dem ein Lesen des Quorums erforderlich ist, ist die Wiederherstellung bei einem Neustart der Datenbankinstanz. Der anfängliche Satz von LSN-Markern muss durch Abfragen von Speicherknoten rekonstruiert werden.

Die Grundlage für Innovationen

Viele neue Aurora-Funktionen werden direkt durch die verteilte, selbstheilende Speicherarchitektur ermöglicht. Dazu gehören:

Lese-Skalierbarkeit: Zusätzlich zur Master-Datenbankinstanz können in Aurora bis zu 15 Lese-Replikate über mehrere Zonen hinweg bereitgestellt werden, um die Leseskalierbarkeit und höhere Verfügbarkeit zu gewährleisten. Lese-Replikate verwenden das gleiche gemeinsame Speichervolumen wie der Master.

Kontinuierliche Sicherung und zeitpunktgenaue Wiederherstellung: Die Aurora-Speicherschicht sichert kontinuierlich und transparent Redo-Log-Streams auf Amazon S3. Sie können einen Point-in-Time-Restore für jeden Zeitstempel innerhalb des konfigurierten Sicherungsfensters durchführen. Es ist nicht erforderlich, die Erstellung von Snapshots zu planen, und es gehen keine Transaktionen verloren, wenn der gewünschte Snapshot weiter zurück liegt.

Schneller Klon: Die Aurora-Speicherschicht kann schnell eine physische Kopie eines Volumes erstellen, ohne alle Seiten kopieren zu müssen. Seiten werden zunächst zwischen übergeordneten und untergeordneten Volumes geteilt, wobei das Kopieren beim Schreiben abgeschlossen wird, wenn Seiten geändert werden. Es fallen keine doppelten Kosten an, wenn ein Volume geklont wird.

Backtrack: Backtrack ist eine schnelle Möglichkeit, die Datenbank auf einen bestimmten Stand zu bringen, ohne eine vollständige Wiederherstellung aus einem Backup durchführen zu müssen. Falls Sie versehentlich einen Eintrag gelöscht haben, können Sie die Zeit mit Aurora Backtracking zurückdrehen.

Es wird noch viele weitere Innovationen rund um relationale Datenbank-Technologie geben, die auf der Basis von Aurora entwickelt wurden. Die Kundenresonanz auf Aurora ist durchweg positiv. Führende Unternehmen in unterschiedlichen Branchen – wie Capital One, Dow Jones, Netflix und Verizon – migrieren ihre relationalen Datenbank-Workloads nach Aurora, einschließlich MySQL- und PostgreSQL-kompatibler Editionen.

Geschrieben von
Werner Vogels
Werner Vogels
Werner Vogels ist Chief Technology Officer (CTO) und Vizepräsident von Amazon.com. Werner bloggt unter https://www.allthingsdistributed.com.
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
4000
  Subscribe  
Benachrichtige mich zu: