MongoDB - Einige Gedanken bezüglich Sharding

Post date: Jan 19, 2014 9:34:26 AM

Die Auswahl eines Sharding-Schlüssels

Es ist entscheidend, von Anfang an den richtigen Sharding-Schlüssel auszuwählen weil es später unmöglich ist, ihn zu ändern. Weil das Sharding-Prinzip von MongoDB ist

verschiedene, eindeutige, nicht überlappende Intervalle innerhalb eines Shards zu betrachten, ist es wichtig einen Schlüssel hinzufügen, der das Wachstum der Daten und deren anwendungsspezifische Zugriffsmuster optimal widerspiegelt. Der Hauptgedanke hinter dieser wichtigen Entscheidung ist die Erzeugung der Hotspots zu vermeiden.

Was wäre als Sharding-Schlüssel empfehlenswert: ein zusammengesetzter Schlüssel der ein grob-steigendes Feld und ein häufig durchsuchbares Feld auf Anwendungsebene enthält. Das durchsuchbare Feld soll über eine dezente Kardinalität verfügen. Ein gutes Beispiel dafür wäre die Kombination zwischen Monat und Nutzer-ID.

Was wäre als Sharding-Schlüssel zu vermeiden: Felder die über eine niedrige Kardinalität verfügen (das heißt, dass sie nur eine kleine, finite Menge von möglichen

Werten haben können), grundsätzlich steigende Felder (wie z.B. Datenbank-Sequenzen oder Zeitstempel) und beliebige Schlüssel. Die Rationalität hinter einer solchen Empfehlung ist dass solche Schlüssel das Potential haben, Hotspots zu erzeugen. Es kann auch der Fall sein, dass die Datenmenge kontrollierbar ist und für manche Anwendungen solche Schlüssel sinnvoll und praktisch sind.

Gibt es irgendwelche Grenzen?

Wenn man will, Sharding auf eine bereits vorhandene Collection die Daten enthält zu aktivieren, muss man die Erzeugung des Indizes für den Sharding-Schlüssel erstmals betrachten. Der Index wird automatisch erstellt nur wenn die Collection neu angelegt wird und ohne diesen Index kann das Sharding einer Collection nicht stattfinden.

Wenn die vorhandene Collection Daten von mehr als 256 GB (manchmal auch 400 GB) enthält, dann wird der initiale Sharding-Prozess nur einen Chunk erzeugen. Nur später, wenn mehrere Dokumente hinzugefügt werden, wird Mongo DB den vorhandenen Chunk in mehrere Chunks aufteilen und dann den Balancing-Ablauf auslösen. Das wird eine Weile dauern. Die exakten Grenzen dieser Collection-Größen werden als einer Funktion der Dokumentengröße und Shard-Größe berechnet.

Skalierung

Ein Shard stellt eine Menge von Servern (einen Replica Set) dar. Die Skalierung auf Shard-Ebene muss auf Replica Set - Ebene stattfinden wo die Anzahl der Server wie gewöhnlich erhöht werden kann.

Man sollte am besten drei Config-Server laufen lassen um optimale Verfügbarkeit und Ausfallsicherheit gewährleisten zu können.

Performance-Betrachtungen

Das Sharding schlißt das Aufladen des Sharding-Schlüssel basierten Index in den RAM-Speicher und die Inpizierung der gesamten Collection die ge-sharded werden soll, ein. Das bedeutet dass sowohl der CPU als auch der Speicher-Verbrauch während dieses Ablaufs gesteigert sein wird, so ist es empfehlenswert, diese Operation durch einen Zeitraum laufen zu lassen, während das MongoDB-Cluster nicht unter Last steht.

Das Ausgleichen von Shards erzeugt erhöhte Last auf RAM-Speicher-Ebene so macht es Sinn, Shards früher und relativ oft, auf kontinuierliche Weise hinzufügen und nicht nur wenn die oberen Grenzen der RAM Memory Kapazität schont erreicht sind. Normalerweise der Shard-Ausgleichen-Ablauf der entweder durch das Hinzufügen neuer Shards oder durch das Löschen vorhandener Shards ausgelöst wird, beeinflusst den Datentraffic nur gering wenn dieser Prozess der Änderungen auf Shard-Ebene zum richtigen Zeitpunkt ausgeführt werden. Begrenzungen des RAM Speichers verursachen Zugriffe auf die Festplatte durch die Anwendung und durch das Ausgleichen von Shards die in diesem Fall leider zu verlängerten Antwortzeiten wesentlich beitragen.

Das Sharding der vorhandenen Collections die kleinere Dokumente enthalten ist teuerer alas das Sharding der Collections mit größeren Dokumenten.

Backup & Restore

Backups für einzelne Shards zu erzeugen zusammen mit deren Wiederherstellung können Informationen entweder duplizieren oder verlieren falls Shard-Ausfälle auftreten und während des Backups Chunk-Migrationen stattfinden. Um den Prozess besser kontrollieren zu können ist es empfehlenswert die Einstellungen der Config-Server zu überprüfen und die Chunk-Collections zu inspizieren um herauszufinden auf welche Shards sich die verschiedenen Chunks befinden.

Wenn man einen Backup für das gesamte MongoDB Cluster zu erzeugen will, muss man den Balancer ausschalten um die verschiedenen Chunk-Migrationen die stattfinden zu vermeiden um dann mittels eines fsyncs die Slaves zu blockieren und Snapshots dafür zu erstellen. Die Wiederherstellung des gesamten Clusters wird das Entsperren der Slaves und das Wiederstarten des Balancers beanspruchen.

Eine andere wichtige Angelegenheit für das Backup & Restore Thema liegt im Zusammenhang mit den Config-Servers die immer in eine redundante Konfiguration laufen müssen. Die Backups von diesen Config-Servers erfolgen schnell weil diese nur geringe Mengen von Daten enthalten.

Einige Aspekte die bei der Interaktion mit einem Cluster berücksichtigt werden müssen

Die Zählung der Dokumente die von einer sharded Collection enthalten sind kann ungenaue Ergebnisse verursachen falls diese Operation während der Chunk-Migration von einem Shard zum anderen ausgeführt wird. Die Eindeutigkeit kann garantiert werden nur wenn alle Shards während einer Schreiboperation gesperrt werden. Die Auswirkung dafür ist dass nur der Sharding-Schlüssel eindeutige Ergebnisse gewährleisten kann. Die Aktualisierung eines einzelnen Dokuments verweist auf die selbe oben gennante Einschränkung, das heißt das der Sharding-Schlüssel immer übergeben werden soll um ein einzelnes Dokument modifizieren zu können.

Map-Reduce Jobs werden gewöhnlich schneller auf einem Cluster als auf einem einzigen MongoDB Server ausgeführt aber sie sind für Echtzeit-Berechnungen nicht befriedigend.

Asynchrone Kommunikation mit einem MongoDB Sharded-Cluster ist sowohl auf Inbound-Ebene als auch auf Outbound-Ebene empfehlenswert insbesondere um Traffic-Explosionen zu glätten und um geplante und ungeplante Ausfälle effizient zu behandeln. Amazon SQS aber auch MongoDB Capped-Collections die auf einer individuellen MongoDB Instanz (die nicht Teil des zu apsichernden Cluster ist) gespeichert wird wären gute Lösungen dafür.

Das Behandeln der Ausfälle

Die Unverfügbarkeit eines gesamten Shards verursacht Fehler auf Anwendungsebene wenn Lese- und Schreibzugriffe ausgeführt werden. Man behandelt solche Fälle elegant wenn man partielle Ergebnisse zurückliefert oder wenn man gezielte Abfragen gegen verfügbaren Shards laufen lässt. Um die Wahrscheinlichkeit gesamte Shards zu verlieren zu minimieren ist es ratsam einen Replica Set für einen Shard einzusetzen um Ausfälle in einer intelligenten Art und Weise behandeln zu können.

Wenn man einen Config-Server verliert, trotz einer redundanten Setup-Konfiguration, wird die Cluster-Configuration unveränderbar bleiben. Normalerweise wird die Auswirkung eines solchen Ereignisses nicht signifikant ausfallen aber ein Nachteil gibt es schon: keine Änderungen auf Cluster-Ebene während ein Config-Server ist unverfügbar können ausgeführt werden. Falls Chunk-Migrationen während dieser Zeitspanne statsinden dann können auch Performance-Auswirkungen auftreten weil diese Chunks von einem Shard zum anderen kopiert werden müssen.

Der Mongos zustandlose Prozess stellt die einzige Kommunikationsbridge zwischen jener Anwendugsebene und einem MongoDB sharded Cluster Setup dar. Es ist ratsam, den redundanten Setup von diesen mongos Prozessen in Erwägung zu ziehen um die Verfügbarkeit der Anwendung zu erhöhen und Ausfälle elegant auf Anwendungebene zu behandeln. Um diese Aspekte zu garantieren muss die Anwendung mit einer Liste von Mongos Instanzen konfiguriert werden und dann wird die Bibliothek die den Treiber für die MongoDB Cluster-Verbindung darstellt die Wierderherstellung der Connections effizient behandeln.