Alle Projekte, mit denen ich bisher zu tun hatte, erforderten nur eine einzige Datenbank auf einem einzigen Server. Ich möchte mehr darüber erfahren, wie Projekte, die skaliert werden müssen, auf mehrere Datenbanken und / oder Server verschoben werden, um die Auslastung zu verwalten. Ich bin mir der hohen Skalierbarkeit bewusst , interessiere mich aber besonders für einige Codebeispiele oder zusätzliche Ressourcen, in denen ich mehr zu diesem Thema lesen kann.
Zum Beispiel:
- Wie werden Joins zwischen zwei Tabellen in mehreren Datenbanken erstellt? (Ein Codebeispiel hier wäre hilfreich).
- Gibt es spezielle Strategien, um zu verfolgen, welche Tabellen sich in welcher Datenbank befinden?
- Muss der Anwendungscode wissen, dass eine oder mehrere Datenbanken auf mehrere Server verteilt sind? Wenn nicht, auf welcher Ebene werden die Anforderungen gefiltert?
- Wann ist es an der Zeit, über ein 1-Datenbank / 1-Server-Setup hinauszugehen? Wie häufig muss das gemacht werden?
Antworten:
Ok, lass es uns zusammenfassen:
Das ist ziemlich einfach. SQL-Objekte haben eine ein- bis vierteilige Namenskonvention:
Servername.datendatenname.schemaname.tabellenname
Wenn sich alle Ihre Tabellen auf demselben Server in derselben Datenbank mit demselben Eigentümer / Schema befinden, können Sie die ersten drei Teile einfach ignorieren und das verwenden, was Sie am häufigsten gewohnt sind:
Wenn sich eine Ihrer Tabellen in einer anderen Datenbank befindet und beide das Standardschema für ihre Datenbanken verwenden, fügen Sie die Datenbank einfach der zweiten Tabelle hinzu:
Wenn Sie sich in einer dritten Datenbank befinden, die sich von der abgefragten unterscheidet, verwenden Sie beide Datenbanknamen explizit:
Wenn Sie unterschiedliche Schemata und / oder Eigentümer verwenden, können Sie diese hinzufügen in:
Und zu guter Letzt können Sie, wenn Sie sehr vorsichtig sind und einen guten Grund haben, einer (normalerweise kleinen) Tabelle auf einem anderen Server beitreten:
Ich werde diese beiden kombinieren, weil sie zusammenpassen. Es ist fast immer in Ordnung, mit der Annahme zu beginnen, dass eine Datenbank und ein Server ausreichen, bis Sie aufgrund Ihrer gestalterischen, geschäftlichen und technischen Einschränkungen gezwungen sind, mehr zu verwenden.
Zur Beantwortung Ihrer zweiten Frage sollten Sie also zunächst wissen, wo sich etwas befindet, da Sie im Allgemeinen einen Grund dafür haben, separate Datenbanken zu haben.
Wann und warum es notwendig ist, über eine einzelne Datenbank hinauszugehen. Normalerweise ist es eine Mischung aus Geschäftsregeln, politischen und / oder technischen Gründen.
Zum Beispiel, wo ich arbeite, haben wir 16 Datenbanken, die auf 4 Server verteilt sind. Wir haben eine MainDB, eine ImageDB, eine referencetableDB, eine HighvolumeTransactionDB, eine ReportingDB, eine StagingDB, eine ProcessingDB, eine ArchiveDB, eine FinancialDB. Um einige Beispiele zu nennen, warum sie unterschiedlich sind:
• Muss der Anwendungscode wissen, dass eine oder mehrere Datenbanken auf mehrere Server verteilt sind? Wenn nicht, auf welcher Ebene werden die Anforderungen gefiltert?
Im weitesten Sinne tun sie es wahrscheinlich. Sie müssen mindestens wissen, auf welchen Server sie in der Datenbankverbindungszeichenfolge verweisen. Verarbeitung, Berichterstattung, Main, etc.
Von dort aus benötigen sie einen Datenbankkontext, unter dem sie ausgeführt werden können. Im Allgemeinen ist dies die am häufigsten verwendete Version für die Anwendung, möglicherweise sogar die ursprüngliche Version aus einer Datenbank / einem Servertag der Anwendung. Sie können festlegen, dass die Anwendung den Datenbankkontext bei jedem Aufruf explizit wechselt. Dies macht es jedoch sehr schwierig, die Datenbank anzupassen, ohne die App zu ändern.
Der übliche (oder zumindest MEINE übliche) Ansatz besteht darin, immer über eine oder vielleicht zwei Hauptdatenbanken zuzugreifen.
Erstellen Sie dann nach Bedarf Ansichten in anderen Datenbanken und stellen Sie eine Verbindung mit der Datenbank über gespeicherte Prozeduren her.
Um dies zu veranschaulichen:
Angenommen, Sie möchten die demografischen Informationen, Verkaufsdaten und das Guthaben eines Kunden abrufen, die ursprünglich alle in der MainDB auf drei Tabellen verteilt waren.
So schreiben Sie einen Anruf von Ihrer App aus:
Genial. Jetzt müssen Sie den App-Code jedoch jedes Mal aktualisieren, wenn wir einen Spaltennamen ändern oder eine Tabelle umbenennen / verschieben. Also machen wir stattdessen zwei Dinge:
Kunden erstellen, Verkauf, AccountReceivables Views (Sie würden nicht Select * verwenden, aber ich probiere es hier aus)
Dann würden wir auch eine gespeicherte Prozedur, spGetClientSalesAR, erstellen
Und lassen Sie Ihre App das nennen.
Solange ich die Oberfläche dieses gespeicherten Prozesses nicht ändere, kann ich so ziemlich alles tun, was ich tun muss, um die Back-End-Datenbank zu vergrößern oder zu verkleinern.
Im Extremfall könnte ich meine alte MainDB sogar zu einer Reihe von gespeicherten Prozeduren und Ansichten mit Shell machen, so dass unter den von uns erstellten Ansichten Folgendes aussieht:
Und Ihre App würde niemals den Unterschied erkennen (unter der Voraussetzung, dass schnelle Pipes und gut bereitgestellte Daten vorhanden sind).
Das ist natürlich extrem und ich würde lügen, wenn ich sagen würde, dass alles so geplant ist. Die Verwendung gespeicherter Prozeduren / Ansichten, auch wenn Sie dies während des Refactorings tun, ermöglicht Ihnen viel Flexibilität, da Ihre App von einer einfachen Datenbank auf einen Server erweitert wird Anfang.
quelle
Die Hauptmethode, mit der ich in der Webwelt auf mehrere Datenbankserver gestoßen bin (da die Frage mit PHP gekennzeichnet ist), sind Setups, bei denen es eine "Master" -Datenbank (Schreiben) und dann eine oder mehrere replizierte "Slave" -Datenbanken (Lesen) gab . Datenbankschreibvorgänge werden für die 'master'-Datenbank ausgeführt. Der Inhalt dieser Datenbank wird nahezu in Echtzeit auf die Slave-Server repliziert. Abfragen - besonders intensive Berichte - werden dann für eine der "Slave" -Datenbanken ausgeführt, um die Last auf diese Server zu verlagern. Denken Sie daran, dass dieses spezielle Setup am besten für Anwendungen geeignet ist, die viel lesen, aber nicht viel schreiben. Es ist keineswegs die einzige Möglichkeit, Dinge zu arrangieren.
quelle
Sie sind nicht. NoSQL-Datenbanken führen überhaupt keine "Joins" durch, und selbst wenn Sie einen SQL-Join über RDBMS-Server hinweg durchführen könnten , würden Sie dies nicht möchten, wenn Sie Wert auf Leistung legen (vgl. Fehler bei verteiltem Computing ).
In einer relationalen / SQL-Datenbank erfolgt die Partitionierung normalerweise innerhalb der Grenzen eines einzelnen Servers / einer einzelnen Datenbank, wobei unterschiedliche Dateien auf unterschiedlichen Datenträgern abgelegt werden. Beinahe per Definition bedeutet eine horizontale Skalierungslösung, dass alle Datenbanken alle Tabellen enthalten und dass Sie über eine Transaktionsspiegelung, Replikation oder eine benutzerdefinierte Lösung für eventuelle Konsistenz verfügen, um sicherzustellen, dass alle Daten dort ankommen, wo sie hingehören.
Wenn Sie die Datenbank tatsächlich logisch und nicht nur physisch aufteilen, erklären die in Ihrer DAL oder ORM definierten Zuordnungen, welche Tabellen sich in welcher Datenbank befinden.
NoSQL-Datenbanken sind eine Mischung aus Partitionierungslösungen. Manchmal sind es die "Tabellen" (oder allgemeiner "Sammlungen"), die partitioniert werden. Ein anderes Mal sind es die "Zeilen" (oder "Dokumente"). In einigen Fällen sind es tatsächlich die Spalten , wie in einer spaltenorientierten Datenbank wie HBase. Es hängt ganz von der Technologie ab, die Sie verwenden. Allen ist gemeinsam, dass die Engine selbst den Überblick über alles behält. Sie müssen also lediglich ein Dokument oder eine Zeile anfordern.
Dies setzt natürlich voraus, dass Sie die Sharding-Funktionen tatsächlich nutzen und nicht nur eine Reihe verschiedener Datenbanken erstellen. Wenn Sie Letzteres tun, dann sind Sie auf sich allein gestellt.
Wenn es sich um unterschiedliche logische Datenbanken handelt, ja. Wenn sie nur physisch verteilt sind, dann nein - vorausgesetzt, dass entweder Ihre spezifische Datenbank Sharding von Haus aus unterstützt oder Sie eine Lastausgleichslösung (für SQL-Datenbanken) verwenden. Nehmen Sie außerdem an, dass alle Ihre Vorgänge zustandslos sind. Wenn Sie horizontale Skalierung wünschen, müssen Sie auf ACID verzichten.
Es ist an der Zeit, dass Sie alles auf einem Server optimiert haben, was Sie können, und die Leistung aufgrund von Einschränkungen bei der E / A-Last immer noch nicht ausreizen können. Wenn Sie die Frage stellen müssen, ist es zu früh.
Beachten Sie, dass Leistungsprobleme in einem anständigen RDBMS-Produkt (Oracle, SQL Server) häufiger auf schlechtes Design, schlechte Indizierung, schlechte Abfragen, Sperrenkonflikte usw. zurückzuführen sind. Diese Produkte können in lächerlichem Maße vertikal skalieren. Sie sollten sich also erneut überlegen, "über ein 1-Datenbank / 1-Server-Setup hinauszugehen", wenn Sie absolut sicher sind, dass Ihre Leistungsprobleme auf Hardwareeinschränkungen und nicht nur auf ein unterdurchschnittliches Design / eine unterdurchschnittliche Implementierung zurückzuführen sind.
Ein weiterer Grund, warum manche Leute auf verteilte Datenbanken umsteigen, ist, dass sie nicht bereit sind, viel (oder gar kein) Geld für Lizenzgebühren zu zahlen, und SQL als bewusste Wahl ablegen möchten, um die niedrigen Kosten für eine erhöhte Anwendungskomplexität einzutauschen. Ein triftiger Grund, wenn Sie ein Software-Startup sind, aber normalerweise nicht für den Unternehmenssektor geeignet sind.
quelle
Es gibt drei Haupttypen von Replikationskonfigurationen für Datenbanken:
Master-Slave-Beispiel: MySQL-Master + MySQL-Slaves, MongoDB
Master-Master-Beispiel: CouchDB, Cassandra, Riak
Konsensbeispiel: ScalienDB
...um ein paar zu nennen.
Diese haben unterschiedliche Eigenschaften. Master-Slave-Konfigurationen ermöglichen es Slave-Knoten, den Master mit maximaler Geschwindigkeit einzuholen, während Leseanforderungen sehr schnell bearbeitet werden, während der Master-Server für die Datenintegrität verantwortlich ist. Da alle Schreibvorgänge an den Master gehen, gibt es keine Sperrkonflikte, da ein einziger relativ langsamer Writer viele Leser blockiert. Andererseits sind die Slave-Server schließlich konsistent und Sie erhalten nicht die Transaktionsisolationsgarantien, die Sie haben würden vom Lesen nur vom Meister. (Weitere Informationen: ACID vs BASE, Transaktionsisolationsstufen, Datenbankreplikation, MVCC / Isolation: Snapshot, Transaktionsreplikation)
Master-Master erlaubt immer Schreibvorgänge, sodass Sie über mehrere Berechtigungen verfügen, was wahr ist. Dies kann ein Problem sein oder auch nicht, je nachdem, was Ihre Anwendung tut. Wenn Sie jedoch widersprüchliche Daten schreiben, erhalten Sie möglicherweise beim nächsten Lesen des Schlüssels / der Zeile / Spalte mehrere Ergebnisse, die Sie mit der Anwendungslogik und zusammenführen müssen Speichern Sie zurück in die Datenbank. (Weiterführende Literatur: CAP-Theorem, CouchDB-Replikation, Riak-Replikation, konsistentes Hashing, Bitcask & StormDB, Quorum-w / MongoDB über Netzwerksplit, Merge Resolution-Strategien)
Konsensbasierte Datenbanken mit knotenübergreifender Replikation, z. B. Scalien, wären beim Schreiben immer konsistent, jedoch auf Kosten des Austauschs mehrerer Nachrichten, bevor das Schreiben bestätigt wird. Dies ist kein großes Problem, wenn Sie über ein schnelles Ethernet verfügen und nicht vor dem ACKing auf die Festplatte schreiben müssen. Dies ist nicht erforderlich, wenn sich mindestens drei Server in verschiedenen Server-Racks mit separaten Netzteilen befinden (einer) stirbt, die anderen beiden stellen sicher, dass sie auf der Festplatte gespeichert haben). (weiterlesen; PAXOS, PAXOS COMMIT, Zwei-Phasen-Commit bei verteilten Transaktionen, Drei-Phasen-Commit)
Weiterführende Literatur: (Buch: 'Elements of Distributed Computing', Vektoruhren, Versionsvektoren, Matrixvektoren, logische Uhren, Bäckereialgorithmus, Intervallbaumuhren, Akteure und reaktive Programmierung und Reaktoren, Software-Transaktionsspeicher, Transaktoren, AKKA, Stact, Irrtümer des Distributed Computing, Klatschprotokolle, Cassandras Anti-Entropie-Klatschprotokoll-Erweiterungen, verteilte Hash-Tabellen, Artikel zum Zusammenführen von Daten in einer verteilten Umgebung, ZooKeeper-Architektur, InfoQ-Präsentation zu "asynchronem Protokoll", HBase-Architektur, MapReduce-Papier, Amazon Dynamo-Papier das alles begann NoSQL-Zeug, Warteschlangen, Rabbitmq-Hochverfügbarkeits-Clustering)
Ich hoffe, ich habe ein bisschen nachgedacht :). Du kannst mir auf Twitter @henrikfeldt folgen, wenn du auch Tweets über dieses Zeug möchtest.
quelle
OK, hier ist ein weiterer Gesichtspunkt zur Skalierbarkeit.
Lassen Sie uns diskutieren, was es bedeutet, Daten zu sein, was es bedeutet, Verhalten zu haben und was es bedeutet, Anwendungslogik zu haben.
Wenn man sich in das Land der Unternehmensanwendungen und dergleichen wagt, wird man normalerweise der Idee der Schichtung ausgesetzt. Natürlich ist das Layering auf Computern allgegenwärtig, z. B. im Netzwerkstapel (ISO-Modell) oder in Grafiken (Photoshop) oder in SOA (Dienste können Geschwister oder Kinder, aber niemals Eltern nennen).
Die spezifische Art der Schichtung, die missbraucht wurde, ist jedoch die der 'GUI', 'Business Logic Layer' und dann 'Data Access Layer'. Ich meine, ja, die Idee ist im Prinzip gut, wie der Kommunismus im Prinzip gut ist, aber in Wirklichkeit ist es nicht.
Werfen wir einen Blick darauf, warum. Das Argument, das ich verwenden werde, ist über die Kopplung; Punkte aus einer Ebene, die Punkte auf einer anderen Ebene berühren. Immer wenn Sie im Standard-Enterprise-Modus eine n-Tier-App (auch bekannt als Layered-App) erstellen, werden so viele Kontaktpunkte zwischen den Ebenen hergestellt.
Im Kern geht es darum, dass Schichten austauschbar sind. aber sie sind nicht! Warum? Wegen der ganzen Koppelung an den Einsatzort.
Schauen Sie sich stattdessen an, warum das Netzwerk entkoppelt ist! Weil die Schnittstelle ein Byte-Stream über einen einzelnen Dateizeiger ist, der auf einen offenen Socket zeigt! Alle Ebenen in den ISO-Modellen entsprechen dem Entwurfsmuster "Chain of Responsibility" zur Objektorientierung! Jede Ebene umschließt die zugrunde liegende Ebene, ohne die Semantik der Daten in dieser zugrunde liegenden Ebene zu kennen.
Während ein Datenpaket in Richtung Ethernet und rohen elektrischen Signalen am unteren Rand wandert, wird es kontinuierlich von Schichten umhüllt, die nur seinen eigenen spezifischen Nachrichtenumschlag kennen, seinen eigenen spezifischen "Stapel von Bytes", die es senden kann. und sonst nichts. Die Aufrufpfade müssen nicht in Abhängigkeit vom Inhalt des Pakets geändert werden.
Vergleichen Sie dies mit n-Tier, bei dem Sie den Aufrufpfad in Ihren Anwendungsebenen bei einem "Aufruf" ändern müssten, der Ihre Ebenen auf dem Weg zur Datenbank durchläuft. Beispielsweise sind "Goldkunden" eine polymorphe Obermenge von "normalen Kunden". Da wir also "Tabelle pro Unterklasse" verwenden, müssen wir dies jetzt wissen, da die Daten (Entitäten) die Ebenen durchlaufen. sowohl in der sogenannten "Business-Logik-Schicht" als auch in der Datenschicht, die tatsächlich das Speichern durchführt.
Es ist weder skalierbar noch vom Computer aus optimal.
Warum ist es nicht skalierbar? Weil die Architektur gekoppelt ist und Sie sich dann immer noch in derselben alten Datenbank befinden, die Sie auf viele Knoten skalieren wollten! Da Sie hierfür jedoch ACID benötigen, müssen Sie diese und eine dritte Entität (Datenobjekt) in einer einzigen Datenbank haben, die Transaktionen ausführt!
Righty, also mit diesem Geschwätz aus dem Weg; Welche anderen Möglichkeiten gibt es?
Nun, es gibt das verhasste Akronym 'SOA', dh serviceorientierte Architektur. Natürlich, die Tomas Erls der Welt , würden Sie alle Ihre Ebenen implementieren lassen, aber stattdessen mit XML und SOAP.
Aus all den oben genannten Gründen ist dies der falsche Weg, da Sie sich an diese XML-Proxys koppeln würden, genau wie Sie sich an die oben erläuterten Anwendungsebenen koppeln würden.
Verwenden Sie stattdessen Messaging, und lassen Sie die Funktionen, die für sie implementiert sind, abhören. Ihre Serviceoberfläche wird dann zu einer Liste von Nachrichten, die Sie senden können, und Sie haben Ihre Vorgänge nicht an Ihre Servicefassade gekoppelt. und Sie müssen nicht einmal wissen, welche Anwendung oder welcher Endpunkt diese Vorgänge implementiert, da Sie lediglich eine Nachricht veröffentlichen, die von einem anderen Routing-Mechanismus an den richtigen Verbraucher weitergeleitet wird!
Da Sie die Servicefassaden von den tatsächlich auszuführenden Vorgängen abgekoppelt haben, können Sie jetzt mehrere Services hinzufügen. Genau so macht es Netflix. Schauen Sie sich diese Präsentationen an: http://www.slideshare.net/adrianco/global-netflix-platform . http://www.slideshare.net/adrianco/global-netflix-platform . Sie sind gut!
quelle
In der Beta- Version gibt es eine neue SQL-Datenbank (ACID) mit angeblich elastischen Skalierungseigenschaften. Derzeit läuft ein kostenloses Beta-Programm, und ich schlage vor, Sie schauen es sich an. Es heißt NuoDB.
Anscheinend übertrifft es MySQL sogar auf einer Maschine mit einem Thread leicht, lässt sich jedoch in bestimmten Benchmarks problemlos auf über 70 Instanzen skalieren.
quelle