MySQL-Sharding-Ansätze?


88

Was ist der beste Ansatz zum Sharding von MySQL-Tabellen? Die Ansätze, die ich mir vorstellen kann, sind:

  1. Sharding auf Anwendungsebene?
  2. Sharding auf MySQL-Proxy-Ebene?
  3. Zentraler Suchserver für Sharding?

Kennen Sie interessante Projekte oder Tools in diesem Bereich?

Antworten:


115

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

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

Sie partitionieren Partitionen und weisen sie dann nur dann verschiedenen Hosts (= Shard) zu, wenn die Summe aller dieser Partitionen nicht mehr auf eine einzelne Datenbankserverinstanz passt - der Grund dafür ist entweder Schreiben oder Lesen.

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

Der Lesefall für das Sharding liegt vor, wenn die Daten so groß sind, dass der Arbeitssatz nicht mehr in den Speicher passt und Datenlesevorgänge auf die Festplatte gelangen, anstatt die meiste Zeit aus dem Speicher bereitgestellt zu werden.

Nur wenn Sie haben Scherbe Sie es tun.


In dem Moment, in dem Sie scherben, zahlen Sie auf verschiedene Weise dafür:

Ein Großteil Ihrer 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 gut so, weil es flexibel ist und weil das Schreiben dieser Datenzugriffsprogramme eine langweilige Arbeit ist, die der Geschwindigkeit schadet.

In einer Sharded-Umgebung verbinden 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 Knoten A und B und verbinden Daten daraus mit Daten auf Knoten B und C. Sie beginnen, anwendungsseitige Hash-basierte Join-Auflösungen manuell zu schreiben, um dies zu beheben (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 (zB verwenden Sie SELECT-Anweisungen in Schleifen).

Sie haben eine große Netzwerklatenz.

Normalerweise kann eine SQL-Abfrage lokal aufgelöst werden, und der Optimierer kennt die mit lokalen Festplattenzugriffen verbundenen Kosten und löst die Abfrage so auf, dass die Kosten dafür minimiert werden.

In einer Sharded-Umgebung werden Abfragen gelöst, indem entweder Schlüsselwertzugriffe über ein Netzwerk auf mehrere Knoten ausgeführt werden (hoffentlich mit Batch-Schlüsselzugriffen und nicht mit einzelnen Schlüssel-Lookups pro Roundtrip) oder indem Teile der WHEREKlausel an die Knoten weitergeleitet werden, an denen sie können angewendet werden (das heißt "Bedingungs-Pushdown") oder beides.

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

Sie verlieren viel Ausdruckskraft von SQL.

Ok, das ist wahrscheinlich weniger wichtig, aber Fremdschlüsseleinschränkungen und andere SQL-Mechanismen für die Datenintegrität können nicht mehrere Shards umfassen.

MySQL verfügt über keine API, die funktionierende asynchrone Abfragen zulässt.

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

Voraussetzung dafür ist eine asynchrone Kommunikations-API, die für MySQL nicht gut funktioniert. Die Alternative ist viel Gabelung und Verbindungen in den Kinderprozessen, die die Welt des Saugens auf einem Saisonpass 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 erzielen, muss sich Ihre Anwendung dieser Dinge bewusst sein, und das bedeutet, dass nur Sharding auf Anwendungsebene sinnvoll ist.

Die Frage ist eher, ob Sie automatisch Sharding durchführen möchten (z. B. durch Hashing von Primärschlüsseln bestimmen, welche Zeile in welchen Knoten verschoben wird) oder ob Sie die Funktion manuell aufteilen möchten ("Die Tabellen zur xyz-User Story gehen dahin master, während abc und def verwandte Tabellen zu diesem Master gehen ").

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

Funktionales Sharding hat den Nachteil, dass keine einzelne Tabelle größer als eine Instanz sein kann und die manuelle Aufmerksamkeit eines Designers erforderlich ist.

Funktionales Sharding hat den Vorteil, dass es relativ einfach an einer vorhandenen Codebasis mit einer Reihe von Änderungen durchgeführt werden kann, die nicht übermäßig groß sind. http://Booking.com hat es in den letzten Jahren mehrmals gemacht und es hat gut für sie 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.


2
Das ist eine gute Antwort. Ich möchte jedoch darauf hinweisen, dass Sharding wirklich nur für Anwendungen mit hohem Volumen erforderlich ist und dass sie wahrscheinlich Einnahmen generieren. Eine Sharding-Anwendung eines Drittanbieters behandelt alle Probleme, die Sie mit Joins, Cross-Shard-Transaktionen usw. haben. Wenn Sie eine gute erhalten, bleibt die Integrität einer "relationalen" Datenbank erhalten. Sie haben Recht, dass andere Anwendungen Ihre Datenbank einfach in ein Schlüssel-Wert-Paar verwandeln und damit den Zweck von SQL zunichte machen.
Chantheman

3
Ich habe noch keine kommerzielle oder nicht kommerzielle Sharding-Anwendung gefunden, die erfolgreich die Tatsache verbirgt, dass die Daten jetzt über das Netzwerk verteilt sind und aufgrund des Fehlens latenzbedingter Wartezeiten Latenz oder Inkonsistenz unterliegen. Wenn Sie sharden, wird Ihre Anwendung dies bemerken und Änderungen erfordern. Sie könnten das genauso gut selbst kontrollieren. Es gibt keine Silberkugel, aber es gibt viel Schlangenöl.
Isotopp

1
Sie sollten dbShards auschecken. Es skaliert besser als linear nach der Anzahl der hinzugefügten "Shards". Sie müssen auf der Anwendungsseite nur sehr wenig oder gar keine Änderungen vornehmen, und ja, Ihre Anwendung kennt den Unterschied nicht. Es sendet und empfängt nur Transaktionen wie bei ODBC oder JDBC. dbShards erlaubt auch Shard-Hinweise, wenn Sie mehr Kontrolle über eine Transaktion wünschen. Sie können dbShards genau mitteilen, von welchem ​​Shard Sie lesen oder schreiben möchten.
Chantheman

1
@Gigala Nun, es ist auch nicht notwendig, Zeit damit zu verbringen, eine genau definierte Antwort wie diese zu verfassen, unabhängig von der Breite, aber ich bin froh, dass dies getan wurde, da sich diese Antwort für mich als hilfreich erwiesen hat. Bitte entmutigen Sie Benutzer nicht, bei der Beantwortung nicht "über den Tellerrand hinaus zu denken".
Mewm

12
  1. Sharding auf Anwendungsebene: dbShards ist das einzige mir bekannte Produkt, das "anwendungsbewusstes Sharding" ausführt. Es gibt ein paar gute Artikel auf der Website. Nur per Definition wird anwendungsbewusstes Sharding effizienter sein. Wenn eine Anwendung genau weiß, wohin sie mit einer Transaktion gehen soll, ohne sie nachschlagen oder von einem Proxy umleiten zu müssen, ist dies an sich schneller. Und Geschwindigkeit ist oft eines der Hauptanliegen, wenn nicht das einzige, wenn sich jemand mit Scherben befasst.

  2. Einige Leute "scherben" mit einem Stellvertreter, aber in meinen Augen macht das den Zweck des Scherbens zunichte. Sie verwenden lediglich einen anderen Server, um Ihren Transaktionen mitzuteilen, wo sich die Daten befinden oder wo sie gespeichert werden sollen. Mit anwendungsbewusstem Sharding weiß Ihre Anwendung von selbst, wohin sie gehen muss. Viel effizienter.

  3. Dies ist wirklich das gleiche wie # 2.


Wird dbShards in der Produktion verwendet, wo? Auch ist es nicht Open Source.
Sheki

Auch Ansatz 2 und 3 können unterschiedlich sein, wenn der Proxy basierend auf einem Hash anstelle der Datenbank oder eines Geschäfts nachschlägt.
Sheki

1
dbShards wird mit einer Vielzahl von Kunden produziert, aber nein, es ist kein Open Source. Ich glaube nicht, dass Sie ein gutes Open-Source-Sharding-Produkt finden werden. Und ja, Sie haben Recht, dass ein Hash als Suche verwendet werden könnte, aber in diesem Fall müssen Sie noch einen weiteren "Stopp" einlegen, um Ihre Transaktion in die Datenbank zu bringen. Aus diesem Grund ist das "anwendungsbewusste" Sharding fast immer schneller.
Chantheman

Aber wie gesagt, wenn Sie eine Sharding-Anwendung erhalten, die die Integrität von Beziehungen aufrechterhält, sind Sie in guter Verfassung. Ich erwähne dbShards, weil es das einzige ist, von dem ich weiß, dass es das tut. Und da dies der Fall ist, werden Ihre Schreib- und Lesegeschwindigkeiten linear skaliert. Sie fügen 4 "Shards" hinzu oder Sie teilen Ihren einen MySQL-Server in 4 auf und er wird viermal so schnell ausgeführt.
Chantheman

7

Kennen Sie interessante Projekte oder Tools in diesem Bereich?

Mehrere neue Projekte in diesem Bereich:

  • citusdata.com
  • spockproxy.sourceforge.net
  • github.com/twitter/gizzard/

5

Shard-Query ist eine OLAP-basierte Sharding-Lösung für MySQL. Hier können Sie eine Kombination aus Sharded-Tabellen und nicht gehärteten Tabellen definieren. Die nicht gehärteten Tabellen (wie Nachschlagetabellen) können frei mit Sharded-Tabellen verbunden werden, und Sharded-Tabellen können miteinander verbunden werden, solange die Tabellen durch den Shard-Schlüssel verbunden werden (kein Cross-Shard oder Self-Joins, die Shard-Grenzen überschreiten). Als OLAP-Lösung hat Shard-Query normalerweise eine Mindestantwortzeit von 100 ms oder weniger, selbst bei einfachen Abfragen, sodass es für OLTP nicht funktioniert. Shard-Query dient zur parallelen Analyse großer Datenmengen.

OLTP-Sharding-Lösungen gibt es auch für MySQL. Zu den Closed-Source-Lösungen gehören ScaleDB und DBShards . Zu den Open Source-OLTP-Lösungen gehören JetPants , Cubrid oder Flock / Gizzard (Twitter-Infrastruktur).


3

Bewerbungsniveau natürlich.

Der beste Ansatz, den ich je in diesem Buch gefunden habe

Hochleistungs-MySQL http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064

Kurzbeschreibung: Sie können Ihre Daten in viele Teile aufteilen und ~ 50 Teile auf jedem Server speichern. Es wird Ihnen helfen, das zweitgrößte Problem des Splitterns zu vermeiden - das Neuausgleichen. Verschieben Sie einfach einige von ihnen auf den neuen Server und alles wird gut :)

Ich empfehle Ihnen dringend, es zu kaufen und den Teil "MySQL-Skalierung" zu lesen.


Das von Ihnen empfohlene Buch ist 8 Jahre alt. Behandelt es Sharding, das für die heutigen Technologien relevant ist?
Raffian

1
Es werden einige grundlegende Ansätze zur Skalierung von MySQL behandelt. AFAIK nichts an der Skalierung von MySQL geändert. Die gleichen Sharding- und Replikationstechniken auf App-Ebene werden heutzutage häufig verwendet.
Andrey Frolov

Ich könnte mich irren, aber ich habe in der letzten Woche eine Menge Nachforschungen angestellt und es sieht so aus, als ob mySQL selbst in den letzten 8 Jahren viele Änderungen vorgenommen hat, insbesondere in Bezug auf Partitionierung und Caching. Es gibt eine neue Version, die dieses Jahr herauskommt: amazon.com/High-Performance-MySQL-Optimization-Replication/dp/… Ich habe sie nicht gelesen, aber ich denke, sie deckt die neuen verfügbaren Replikationsmodelle ab.
NateDSaint

4
Bücher .. warum nicht einfach hier erklären.
DDD

2

Ab 2018 scheint es dafür eine MySql-native Lösung zu geben. Es gibt tatsächlich mindestens 2 - InnoDB Cluster und NDB Cluster (es gibt eine kommerzielle und eine Community-Version davon).

Da die meisten Benutzer der MySql Community Edition mit der InnoDB-Engine besser vertraut sind, sollte dies als erste Priorität untersucht werden. Es unterstützt die sofortige Replikation und Partitionierung / das Sharding und basiert auf MySql Router für verschiedene Routing- / Lastausgleichsoptionen.

Die Syntax für die Erstellung Ihrer Tabellen muss sich beispielsweise ändern:

    CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );

(Dies ist nur einer von vier Partitionierungstypen )

Eine sehr wichtige Einschränkung:

InnoDB-Fremdschlüssel und MySQL-Partitionierung sind nicht kompatibel. Partitionierte InnoDB-Tabellen können weder Fremdschlüsselreferenzen noch Spalten enthalten, auf die durch Fremdschlüssel verwiesen wird. InnoDB-Tabellen, die Fremdschlüssel haben oder auf die von Fremdschlüsseln verwiesen wird, können nicht partitioniert werden.


Beachten Sie, dass PARTITION BY HASH(YEAR...)scannt alle Partitionen , wenn Sie einen Datumsbereich haben. Yuck.
Rick James
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.