CockroachDB-Überprüfung: Eine skalierbare SQL-Datenbank zum Überleben

Bis vor kurzem, als Sie für eine Datenbank einkauften, mussten Sie wählen: Skalierbarkeit oder Konsistenz? SQL-Datenbanken wie MySQL garantieren eine hohe Konsistenz, lassen sich jedoch horizontal nicht gut skalieren. (Manuelles Sharding für Skalierbarkeit macht niemandem Spaß.) NoSQL-Datenbanken wie MongoDB lassen sich wunderbar skalieren, bieten jedoch nur eine eventuelle Konsistenz. ("Warten Sie lange genug, und Sie können die richtige Antwort lesen" - was keine Möglichkeit ist, Finanztransaktionen durchzuführen.)

Google Cloud Spanner, ein vollständig verwalteter relationaler Datenbankdienst, der auf Google Compute Engine (GCE) ausgeführt wird und im Februar 2017 veröffentlicht wurde, bietet die Skalierbarkeit von NoSQL-Datenbanken unter Beibehaltung der SQL-Kompatibilität, relationaler Schemata, ACID-Transaktionen und einer starken externen Konsistenz. Spanner ist eine gesplittete, global verteilte und replizierte relationale Datenbank, die einen Paxos-Algorithmus verwendet, um einen Konsens zwischen ihren Knoten zu erzielen.

Eine Alternative zu Spanner und Gegenstand dieser Überprüfung ist CockroachDB, eine horizontal skalierbare verteilte Open-Source-SQL-Datenbank, die von ehemaligen Googlern entwickelt wurde, die mit Spanner vertraut waren. CockroachDB leiht sich für den Entwurf seines Datenspeichersystems von Googles Spanner aus und verwendet einen Raft-Algorithmus, um einen Konsens zwischen seinen Knoten zu erzielen.

CockroachDB ist wie Cloud Spanner eine verteilte SQL-Datenbank, die auf einem transaktionalen und konsistenten Schlüsselwertspeicher basiert, im Fall von CockroachDB auf RocksDB. Die Hauptentwurfsziele von CockroachDB sind die Unterstützung von ACID-Transaktionen, die horizontale Skalierbarkeit und (vor allem) die Überlebensfähigkeit, daher der Name.

CockroachDB wurde entwickelt, um Festplatten-, Maschinen-, Rack- und sogar Rechenzentrumsfehler mit minimaler Latenzunterbrechung und ohne manuellen Eingriff zu überstehen. Um dies zu erreichen, müssen Sie natürlich einen Cluster mit vielen Instanzen der symmetrischen Knoten von CockroachDB ausführen , wobei mehrere Festplatten, Maschinen, Racks und Rechenzentren verwendet werden.

Im Gegensatz zu Cloud Spanner, der die für die Zeitsynchronisation in Google-Rechenzentren verfügbare TrueTime-API verwendet, kann CockroachDB nicht auf das Vorhandensein von Atomuhren und GPS-Satellitenuhren zählen, um die Zeit zwischen Knoten und Rechenzentren genau zu synchronisieren. Das hat eine Reihe von Auswirkungen. Zunächst gibt Google TrueTime eine Obergrenze für Taktversätze zwischen Knoten in einem Cluster von sieben Millisekunden an. Das ist klein genug, dass ein Spanner-Knoten nach einem Schreibvorgang nur sieben Millisekunden wartet, bevor er meldet, dass eine Transaktion festgeschrieben wurde, um die externe Konsistenz zu gewährleisten.

Ohne TrueTime oder eine ähnliche Funktion muss CockroachDB auf NTP zurückgreifen, das Obergrenzen für die Taktsynchronisation zwischen 100 Millisekunden und 250 Millisekunden festlegt. Angesichts dieses größeren Zeitfensters wartet CockroachDB nicht nach dem Schreiben. Stattdessen wartet es manchmal vor dem Lesen und startet eine Transaktion im Grunde neu, wenn es einen Wert mit einem Zeitstempel liest, der größer als der Beginn der Transaktion ist, um wiederum die Konsistenz zu gewährleisten.

Wenn alle Knoten in einem CockroachDB-Cluster die kleinen Obergrenzen für Taktversätze haben, die Sie von GPS- oder Atomuhren erhalten können, was gerade in großen öffentlichen Clouds verfügbar wird, kann es sinnvoll sein, sie mit dem --linearizable Flag auszuführen . Dadurch warten sie genau wie Spanner auf den maximalen Taktversatz, bevor sie ein erfolgreiches Commit zurückgeben.

Wie CockroachDB funktioniert

Jeder CockroachDB-Knoten besteht aus fünf Schichten:

  • SQL, das Client-SQL-Abfragen in Schlüsselwertoperationen übersetzt
  • Transaktion, die atomare Änderungen an mehreren Schlüsselwerteinträgen ermöglicht
  • Verteilung, die replizierte Schlüsselwertbereiche als eine Einheit darstellt
  • Die Replikation repliziert konsistent und synchron Schlüsselwertbereiche über viele Knoten hinweg und ermöglicht konsistente Lesevorgänge über Leases
  • Speicher, der Schlüsselwertdaten auf die Festplatte schreibt und liest

Die SQL-Ebene analysiert Abfragen anhand einer Yacc-Datei und wandelt sie in einen abstrakten Syntaxbaum um. Aus dem abstrakten Syntaxbaum generiert CockroachDB einen Baum von Planknoten, die Schlüsselwertcode enthalten. Die Plan-Knoten werden dann ausgeführt und kommunizieren mit der Transaktionsschicht.

Die Transaktionsschicht implementiert die ACID-Transaktionssemantik mit zweiphasigen Commits im gesamten Cluster, einschließlich bereichs- und tabellenübergreifender Transaktionen, wobei einzelne Anweisungen als Transaktionen behandelt werden (auch als Auto-Commit-Modus bezeichnet). Das zweiphasige Festschreiben wird durchgeführt, indem Transaktionsdatensätze und Schreibabsichten veröffentlicht, Leseoperationen ausgeführt und alle aufgetretenen Schreibabsichten als Transaktionskonflikte behandelt werden.

Die Verteilungsschicht empfängt Anforderungen von der Transaktionsschicht auf demselben Knoten. Anschließend wird festgelegt, welche Knoten die Anforderung empfangen sollen, und die Anforderung wird an die Replikationsschicht des richtigen Knotens gesendet.

Die Replikationsschicht kopiert Daten zwischen Knoten und stellt die Konsistenz zwischen diesen Kopien sicher, indem ein Raft-Konsensalgorithmus implementiert wird. Sie können den Replikationsfaktor auf Cluster-, Datenbank- und Tabellenebene mithilfe von Replikationszonen steuern. Der Konsensalgorithmus wird nur für Schreibvorgänge verwendet und erfordert, dass ein Quorum von Replikaten Änderungen an einem Bereich vereinbart, bevor diese Änderungen festgeschrieben werden.

Die Speicherschicht speichert Daten mithilfe von RocksDB als Schlüssel-Wert-Paare auf der Festplatte. CockroachDB ist stark auf die Mehrfachversions-Parallelitätskontrolle (MVCC) angewiesen, um gleichzeitige Anforderungen zu verarbeiten und Konsistenz zu gewährleisten. Ein Großteil dieser Arbeit wird mithilfe von HLC-Zeitstempeln (Hybrid Logic Clock) ausgeführt.

Wie Spanner unterstützt CockroachDB Zeitreiseabfragen (von MVCC aktiviert). Diese können bis zu Ihrer letzten Datenbank-Garbage-Collection zurückreichen, die standardmäßig täglich durchgeführt wird.

Installation und Verwendung von CockroachDB

CockroachDB läuft auf Mac-, Linux- und Windows-Betriebssystemen, zumindest für Entwicklung und Test. Production Cockroach-Datenbanken werden normalerweise auf Linux-VMs oder orchestrierten Containern ausgeführt, die häufig in öffentlichen Clouds in mehreren Rechenzentren gehostet werden. Die Windows-Binärdatei von CockroachDB befindet sich noch in der Beta-Phase und wird für die Produktion nicht empfohlen. Apple stellt keine Serverhardware mehr her.

Kakerlakenlabore

Wie Sie im obigen Screenshot sehen können, gibt es vier Optionen zum Installieren von CockroachDB auf einem Mac. Ich wählte Homebrew als wahrscheinlich das einfachste der vier.

Übrigens veröffentlicht Cockroach Labs auf der Site eine Warnung, dass das Ausführen einer zustandsbehafteten Anwendung wie CockroachDB in Docker schwierig ist, nicht für Produktionsbereitstellungen empfohlen wird und stattdessen ein Orchestrierungstool wie Kubernetes oder Docker Swarm zum Ausführen eines Clusters verwendet wird. Ich werde im nächsten Abschnitt die Optionen für die Container-Orchestrierung erläutern.

Die Installation auf einem Mac ist so einfach wie brew install cockroachoben gezeigt. In meinem Fall dauerte das automatische Update von Homebrew viel länger (genug Zeit, um Tee zuzubereiten) als die eigentliche Installation von CockroachDB, die nur wenige Sekunden dauerte.

Sobald Sie CockroachDB installiert haben, ist es ziemlich einfach, einen lokalen Cluster hochzufahren, obwohl es den zusätzlichen Schritt gibt, Sicherheitszertifikate mit dem cockroach certBefehl zu generieren, wenn der Cluster sicher sein soll. Sobald ein Cluster ausgeführt wird (mit dem cockroach startBefehl einmal für jeden Knoten, wobei nachfolgende Knoten so eingestellt sind, dass er dem Cluster des ersten Knotens beitritt), können Sie mit einem Browser eine Verbindung zur Webverwaltungsseite auf jedem Knoten herstellen und den eingebetteten cockroach sqlClient zum Senden von SQL verwenden Abfragen an einen beliebigen Knoten. Die meisten Browser beschweren sich über Websites mit von CockroachDB generierten Zertifikaten. Sie sollten jedoch in der Lage sein, durch diese Warnung zu klicken und mit der Website fortzufahren.

Die empfohlenen Produktionseinstellungen für CockroachDB unterscheiden sich von den Standardeinstellungen, die für Entwicklungs- und Testinstanzen eingerichtet wurden. Sie können auf Wunsch einen Cluster mit einem Knoten entwickeln. Für die Produktion sollten Sie mindestens drei Knoten haben, jeden Knoten auf einem separaten Computer, einer VM oder einem Container ausführen und jeder Instanz zusätzlichen Cache und SQL-Speicher zuweisen. Die Standardeinstellungen für Cache und SQL-Speicher sind jeweils 128 MB. Die empfohlenen Produktionseinstellungen geben jeweils 25 Prozent des Arbeitsspeichers an:

cockroach start --cache=25% --max-sql-memory=25%

Je mehr Knoten Sie ausführen, desto besser ist die Ausfallsicherheit. Je größer und schneller die Knoten sind, desto besser ist die Leistung. Wenn Sie Knoten mit einer Leistung haben möchten, die in etwa mit Google Cloud Spanner-Knoten vergleichbar ist, die 2.000 Schreibvorgänge pro Sekunde und 10.000 Lesevorgänge pro Sekunde liefern, dann möchten Sie so etwas wie die n1-highcpu-8-Instanzen von GCE mit acht CPUs und 8 GB RAM mit lokalen SSD-Festplatten (anstatt sich drehende Festplatten).

Je mehr Sie Ihre Knoten auf verschiedene Rechenzentren verteilen, desto besser können Sie die Immunität gegen Ausfälle auf Rechenzentrumsebene sicherstellen. Es gibt jedoch Kosten: Die Round-Trip-Latenz zwischen Rechenzentren wirkt sich direkt auf die Leistung Ihrer Datenbank aus. Kontinentübergreifende Cluster weisen eine deutlich schlechtere Leistung auf als Cluster, in denen alle Knoten geografisch nahe beieinander liegen.

Cockroach Labs bietet detaillierte Anweisungen für die Bereitstellung unter AWS, Digital Ocean, GCE und Azure. In den empfohlenen Konfigurationen werden Load Balancer verwendet, entweder die nativen verwalteten Load Balancing-Dienste oder Open Source-Load Balancer wie HAProxy.

Durch Orchestrierung kann der Betriebsaufwand eines CockroachDB-Clusters auf fast nichts gesenkt werden. Cockroach Labs dokumentiert, wie dies für die Produktion mit Kubernetes und Docker Swarm gemacht wird. Das CockroachDB-CloudFormation-Repository auf GitHub zeigt, wie AWS CloudFormation und Kubernetes in einer einzigen Verfügbarkeitszone für Entwicklung und Test verwendet werden. Um dies für die Produktion anzupassen, muss die CloudFormation-Vorlage so geändert werden, dass mehrere Verfügbarkeitszonen verwendet werden.

Programmierung und Test von CockroachDB

CockroachDB unterstützt das PostgreSQL-Wire-Protokoll, sodass Sie Ihren Code so schreiben, als würden Sie gegen Postgres oder zumindest eine Teilmenge von Postgres programmieren. Auf dieser Seite werden die getesteten Treiber für verschiedene Programmiersprachenbindungen aufgelistet, einschließlich der beliebtesten serverseitigen Sprachen. Diese Seite listet Beispiele in 10 Programmiersprachen und fünf ORMs auf. Ich habe beim Lesen des Codes keine großen Überraschungen erlebt, obwohl ich in den Auflistungen in der Dokumentation einige wahrscheinliche kleinere Fehler entdeckt habe. Sie können Ihre SQL auch mit dem in die cockroachausführbare Datei integrierten interaktiven Client ausführen.

Während es ein Repo für CockroachDB-Lastgeneratoren und ein anderes für Leistungstests gibt, ist das Benchmarking von CockroachDB-Clustern nicht einfach, insbesondere wenn Sie versuchen, CockroachDB auf sinnvolle Weise mit anderen Datenbanken zu vergleichen. Ein Problem ist, dass das Netzwerk zwischen den Knoten der geschwindigkeitsbegrenzende Schritt in CockroachDB-Clustern sein kann.

Eine weitere zu berücksichtigende Tatsache ist, dass die meisten herkömmlichen SQL-Datenbanken standardmäßig nicht im SERIALIZABLE-Isolationsmodus ausgeführt werden. Stattdessen verwenden sie einen weniger strengen Modus mit besserer Leistung. CockroachDB verwendet standardmäßig den serialisierbaren Isolationsmodus. Darüber hinaus wäre es etwas unfair, die SQL-Join-Leistung von CockroachDB, die noch in Arbeit ist, mit der TPC-C-Suite zu testen.

Und doch können Sie die Betriebsleistung von CockroachDB leicht erkennen. Beispielsweise müssen viele Datenbanken gestoppt und neu gestartet werden, um sie zu skalieren. Das Hinzufügen von Knoten unter Last in CockroachDB ist ein Kinderspiel, insbesondere wenn Sie ein Orchestrierungswerkzeug verwenden. Der obige Screenshot zeigt beispielsweise die Befehle zum Ändern und Anzeigen der Knoten in einem Kubernetes-Cluster, und der folgende Screenshot zeigt den überwachten Cluster beim Hinzufügen der Knoten. Während des gesamten Prozesses wurde kontinuierlich ein Tool zur Lastgenerierung ausgeführt.

Eine noch eindrucksvollere Demonstration zeigt die automatische Cloud-übergreifende Migration innerhalb eines CockroachDB-Clusters. Es erfordert wirklich ein Video, um dem gerecht zu werden. Das Video wird im verlinkten Blog-Beitrag gehostet.

CockroachDB SQL 

SQL in CockroachDB ist mehr oder weniger Standard, im Gegensatz zu SQL in Cloud Spanner, das für die Datenmanipulation eine nicht standardmäßige Syntax verwendet. In CockroachDB SQL fehlen jedoch noch viele Funktionen.

In V1.1 fehlt beispielsweise die JSON-Unterstützung, die für V1.2 geplant ist. Es fehlt auch die XML-Analyse, die nicht auf der Roadmap steht. Es fehlen Kaskaden auf Zeilenebene, die für V1.2 geplant sind, und Cursor und Trigger, die nicht auf der Roadmap stehen. Geodatenindizes sind „potenzielle“ Ergänzungen, die es in Zukunft möglicherweise in die Roadmap schaffen.

Vor allem die anfängliche Implementierung von SQL-Joins in CockroachDB im Jahr 2016 war bewusst simpel und zeigte eine quadratische Skalierung, sodass sie für die Abfrage großer Datenmengen unbrauchbar wurde. Die Version in V1.0, die von einem Koop-Studenten erstellt wurde, implementierte Hash-Joins, sodass viele Join-Operationen linear skaliert werden konnten. das brachte CockroachDB auf das Niveau von SQLite. Irgendwann im Jahr 2018 sollte CockroachDB angesichts einer kürzlich durchgeführten Finanzierungsrunde eine Join-Leistung haben, die eher wie PostgreSQL-Joins skaliert, sowie eine über den Cluster verteilte SQL-Join-Verarbeitung.