Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Sharding-Ansätze?

Der beste Ansatz für das Sharding von MySQL-Tabellen ist es, dies nicht zu tun, es sei denn, es ist völlig unvermeidlich.

Wenn Sie eine Anwendung schreiben, möchten Sie dies normalerweise so tun, dass die Geschwindigkeit, die Entwicklergeschwindigkeit, maximiert wird. Sie optimieren die Latenz (Zeit, bis die Antwort fertig ist) oder den Durchsatz (Anzahl der Antworten pro Zeiteinheit) nur bei Bedarf.

Erst wenn die Summe all dieser Partitionen nicht mehr auf eine einzelne Datenbankserver-Instanz passt, partitionieren Sie und weisen sie dann verschiedenen Hosts (=Shard) zu - der Grund dafür sind entweder Schreib- oder Lesezugriffe.

Der Schreibfall ist entweder a) die Häufigkeit der Schreibvorgänge überlastet die Festplatten dieses Servers dauerhaft oder b) es finden zu viele Schreibvorgänge statt, so dass die Replikation in dieser Replikationshierarchie dauerhaft zurückbleibt.

Der Lesefall für Sharding ist, wenn die Größe der Daten so groß ist, dass der Arbeitssatz davon nicht mehr in den Arbeitsspeicher passt und Datenlesevorgänge beginnen, auf die Festplatte zu treffen, anstatt die meiste Zeit aus dem Arbeitsspeicher bedient zu werden.

Nur wenn Sie haben zu Shard tun Sie es.

In dem Moment, in dem Sie teilen, bezahlen Sie dafür auf mehrere Arten:

Ein Großteil Ihres SQL ist nicht mehr deklarativ.

Normalerweise teilen Sie der Datenbank in SQL mit, welche Daten Sie möchten, und überlassen es dem Optimierer, diese Spezifikation in ein Datenzugriffsprogramm umzuwandeln. Das ist eine gute Sache, weil es flexibel ist und weil das Schreiben dieser Datenzugriffsprogramme eine langweilige Arbeit ist, die der Geschwindigkeit schadet.

Bei einer Sharding-Umgebung verknüpfen Sie wahrscheinlich eine Tabelle auf Knoten A mit Daten auf Knoten B, oder Sie haben eine Tabelle, die größer als ein Knoten ist, auf den Knoten A und B und verknüpfen Daten daraus mit Daten auf den Knoten B und C. Sie beginnen, anwendungsseitige Hash-basierte Join-Auflösungen manuell zu schreiben, um das zu lösen (oder Sie erfinden den MySQL-Cluster neu), was bedeutet, dass Sie am Ende viel SQL haben, das nicht mehr deklarativ ist, sondern die SQL-Funktionalität auf prozedurale Weise ausdrückt (Sie verwenden z. B. SELECT-Anweisungen in Schleifen).

Es kommt zu einer hohen Netzwerklatenz.

Normalerweise kann eine SQL-Abfrage lokal aufgelöst werden und der Optimierer weiß um die Kosten, die mit lokalen Plattenzugriffen verbunden sind, und löst die Abfrage so auf, dass die Kosten dafür minimiert werden.

In einer Sharding-Umgebung werden Abfragen aufgelöst, indem entweder Schlüsselwertzugriffe über ein Netzwerk auf mehrere Knoten ausgeführt werden (hoffentlich mit gestapelten Schlüsselzugriffen und nicht einzelnen Schlüsselsuchen pro Roundtrip) oder indem Teile des WHERE verschoben werden -Klausel zu den Knoten weiterleiten, wo sie angewendet werden können (das heißt 'Bedingungs-Pushdown'), oder beides.

Aber selbst im besten Fall beinhaltet dies viel mehr Netzwerkrundfahrten als eine lokale Situation, und es ist komplizierter. Vor allem, da der MySQL-Optimierer überhaupt nichts über Netzwerklatenz weiß (Ok, MySQL-Cluster wird darin langsam besser, aber für Vanilla-MySQL außerhalb des Clusters gilt das immer noch).

Sie verlieren viel Ausdruckskraft von SQL.

Ok, das ist wahrscheinlich weniger wichtig, aber Fremdschlüsselbeschränkungen und andere SQL-Mechanismen für die Datenintegrität sind nicht in der Lage, mehrere Shards zu umfassen.

MySQL hat keine funktionierende API, die asynchrone Abfragen zulässt.

Wenn sich Daten des gleichen Typs auf mehreren Knoten befinden (z. B. Benutzerdaten auf den Knoten A, B und C), müssen häufig horizontale Abfragen für alle diese Knoten aufgelöst werden ("Alle Benutzerkonten finden, die seit 90 Tagen nicht angemeldet sind oder mehr"). Die Datenzugriffszeit wächst linear mit der Anzahl der Knoten, es sei denn, mehrere Knoten können parallel abgefragt und die Ergebnisse bei Eingang aggregiert werden ("Map-Reduce").

Voraussetzung dafür ist eine asynchrone Kommunikations-API, die es für MySQL nicht in einem gut funktionierenden Zustand gibt. Die Alternative sind viele Verzweigungen und Verbindungen in den untergeordneten Prozessen, die die Welt von Suck auf einer Saisonkarte besuchen.

Sobald Sie mit dem Sharding beginnen, werden Datenstruktur und Netzwerktopologie als Leistungspunkte für Ihre Anwendung sichtbar. Um eine einigermaßen gute Leistung zu erbringen, muss sich Ihre Anwendung dieser Dinge bewusst sein, und das bedeutet, dass wirklich nur Sharding auf Anwendungsebene sinnvoll ist.

Die Frage ist eher, ob Sie ein Auto-Sharding durchführen möchten (z. B. durch Hashing von Primärschlüsseln bestimmen, welche Zeile in welchen Knoten geht) oder ob Sie funktional auf manuelle Weise aufteilen möchten ("Die Tabellen im Zusammenhang mit der xyz-Benutzergeschichte gehen zu this master, während abc- und def-bezogene Tabellen an diesen master gehen").

Funktionales Sharding hat den Vorteil, dass es, wenn es richtig gemacht wird, für die meisten Entwickler die meiste Zeit unsichtbar ist, da alle Tabellen, die sich auf ihre User Story beziehen, lokal verfügbar sind. Dadurch können sie noch so lange wie möglich von deklarativem SQL profitieren und haben außerdem weniger Netzwerklatenz, da die Anzahl der netzwerkübergreifenden Übertragungen minimal gehalten wird.

Funktionelles Sharding hat den Nachteil, dass es nicht zulässt, dass eine einzelne Tabelle größer als eine Instanz ist, und es erfordert die manuelle Aufmerksamkeit eines Designers.

Funktionales Sharding hat den Vorteil, dass es relativ einfach an einer bestehenden Codebasis mit einer nicht allzu großen Anzahl von Änderungen durchgeführt werden kann. http://Booking.com hat es in den letzten Jahren mehrfach gemacht und es hat gut funktioniert.

Nachdem ich das alles gesagt habe und Ihre Frage betrachte, glaube ich, dass Sie die falschen Fragen stellen, oder ich verstehe Ihre Problemstellung völlig falsch.