MongoDB Sharding: Praktische Schritt-für-Schritt-Anleitung

Sharding ist ein Prozess, bei dem große Mengen an Datensätzen in einen Teil kleinerer Datensätze über mehrere MongoDB-Instanzen in einer verteilten Umgebung aufgeteilt werden.

Was ist Sharding?

MongoDB-Sharding bietet uns eine skalierbare Lösung, um eine große Datenmenge auf mehreren Servern zu speichern, anstatt sie auf einem einzelnen Server zu speichern.

In der Praxis ist es nicht möglich, exponentiell wachsende Daten auf einer einzigen Maschine zu speichern. Das Abfragen einer großen Datenmenge, die auf einem einzelnen Server gespeichert ist, kann zu einer hohen Ressourcenauslastung führen und bietet möglicherweise keinen zufriedenstellenden Lese- und Schreibdurchsatz.

Grundsätzlich gibt es zwei Arten von Skalierungsmethoden, um mit dem System wachsende Daten zu verarbeiten:

Vertikale Skalierung funktioniert mit der Verbesserung der Leistung eines einzelnen Servers, indem leistungsfähigere Prozessoren hinzugefügt, RAM aktualisiert oder dem System mehr Speicherplatz hinzugefügt wird. Aber es gibt die möglichen Auswirkungen der Anwendung der vertikalen Skalierung in praktischen Anwendungsfällen mit vorhandener Technologie und Hardwarekonfigurationen.

Die horizontale Skalierung funktioniert mit dem Hinzufügen weiterer Server und der Verteilung der Last auf mehrere Server. Da jede Maschine die Teilmenge des gesamten Datensatzes verarbeitet, bietet sie eine bessere Effizienz und eine kostengünstigere Lösung als den Einsatz von High-End-Hardware. Aber es erfordert zusätzliche Wartung der komplexen Infrastruktur mit einer großen Anzahl von Servern.

Mongo DB Sharding arbeitet mit der horizontalen Skalierungstechnik.

Sharding-Komponenten

Um Sharding in MongoDB zu erreichen, sind die folgenden Komponenten erforderlich:

Shard ist eine Mongo-Instanz zur Verarbeitung einer Teilmenge von Originaldaten. Shards müssen im Replikatsatz bereitgestellt werden.

Mongos ist eine Mongo-Instanz und fungiert als Schnittstelle zwischen einer Client-Anwendung und einem Sharding-Cluster. Es fungiert als Abfragerouter für Shards.

Config Server ist eine Mongo-Instanz, die Metadateninformationen und Konfigurationsdetails des Clusters speichert. MongoDB erfordert, dass der Konfigurationsserver als Replikatsatz bereitgestellt wird.

Sharding-Architektur

Der MongoDB-Cluster besteht aus einer Reihe von Replikatsätzen.

Jeder Replikatsatz besteht aus mindestens 3 oder mehr Mongo-Instanzen. Ein Sharding-Cluster kann aus mehreren Mongo-Shards-Instanzen bestehen, und jede Shard-Instanz funktioniert innerhalb eines Shard-Replikatsatzes. Die Anwendung interagiert mit Mongos, das wiederum mit Shards kommuniziert. Daher interagieren Anwendungen beim Sharding niemals direkt mit Shard-Knoten. Der Abfrage-Router verteilt die Teilmengen von Daten basierend auf dem Shard-Schlüssel auf Shards-Knoten.

Sharding-Implementierung

Befolgen Sie die folgenden Schritte zum Sharding

Schritt 1

  • Starten Sie den Konfigurationsserver im Replikatsatz und aktivieren Sie die Replikation zwischen ihnen.

mongod –configsvr –port 27019 –replSet rs0 –dbpath C:datadata1 –bind_ip localhost

mongod –configsvr –port 27018 –replSet rs0 –dbpath C:datadata2 –bind_ip localhost

mongod –configsvr –port 27017 –replSet rs0 –dbpath C:datadata3 –bind_ip localhost

Schritt 2

  • Replikatsatz auf einem der Konfigurationsserver initialisieren.

rs.initiate( { _id : „rs0“, configsvr: true, Mitglieder: [   { _id: 0, host: “IP:27017” },   { _id: 1, host: “IP:27018” },   { _id: 2, host: “IP:27019” }    ] })

rs.initiate( { _id : "rs0",  configsvr: true,  members: [   { _id: 0, host: "IP:27017" },   { _id: 1, host: "IP:27018" },   { _id: 2, host: "IP:27019" }    ] })
{
        "ok" : 1,
        "$gleStats" : {
                "lastOpTime" : Timestamp(1593569257, 1),
                "electionId" : ObjectId("000000000000000000000000")
        },
        "lastCommittedOpTime" : Timestamp(0, 0),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1593569257, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        },
        "operationTime" : Timestamp(1593569257, 1)
}

Schritt 3

  • Starten Sie Sharding-Server im Replikatsatz und aktivieren Sie die Replikation zwischen ihnen.

mongod –shardsvr –port 27020 –replSet rs1 –dbpath C:datadata4 –bind_ip localhost

mongod –shardsvr –port 27021 –replSet rs1 –dbpath C:datadata5 –bind_ip localhost

  10 Möglichkeiten, die zufällige Trennung des Xbox One-Controllers zu beheben

mongod –shardsvr –port 27022 –replSet rs1 –dbpath C:datadata6 –bind_ip localhost

MongoDB initialisiert den ersten Sharding-Server als primär, um die Verwendung des primären Sharding-Servers zu verschieben movePrimary Methode.

Schritt 4

  • Initialisieren Sie den Replikatsatz auf einem der Sharding-Server.

rs.initiate( { _id : „rs0“, Mitglieder: [   { _id: 0, host: “IP:27020” },   { _id: 1, host: “IP:27021” },   { _id: 2, host: “IP:27022” }    ] })

rs.initiate( { _id : "rs0",  members: [   { _id: 0, host: "IP:27020" },   { _id: 1, host: "IP:27021" },   { _id: 2, host: "IP:27022" }    ] })
{
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1593569748, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        },
        "operationTime" : Timestamp(1593569748, 1)
}

Schritt 5

  • Starten Sie die Mangos für den Sharded-Cluster

mongos –port 40000 –configdb rs0/localhost:27019,localhost:27018, localhost:27017

Schritt 6

  • Verbinden Sie den Mongo-Routenserver

Mongo – Port 40000

  • Fügen Sie jetzt Sharding-Server hinzu.

sh.addShard( „rs1/localhost:27020,localhost:27021,localhost:27022“)

sh.addShard( "rs1/localhost:27020,localhost:27021,localhost:27022")
{
        "shardAdded" : "rs1",
        "ok" : 1,
        "operationTime" : Timestamp(1593570212, 2),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1593570212, 2),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

Schritt 7

  • Aktivieren Sie in der Mongo-Shell das Sharding für DB und Sammlungen.
  • Sharding auf DB aktivieren

sh.enableSharding („geekFlareDB“)

sh.enableSharding("geekFlareDB")
{
        "ok" : 1,
        "operationTime" : Timestamp(1591630612, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1591630612, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

Schritt 8

  • Zum Sharden ist der Sammlungs-Shard-Schlüssel (weiter unten in diesem Artikel beschrieben) erforderlich.

Syntax: sh.shardCollection(„dbName.collectionName“, { „key“ : 1 } )

sh.shardCollection("geekFlareDB.geekFlareCollection", { "key" : 1 } )
{
        "collectionsharded" : "geekFlareDB.geekFlareCollection",
        "collectionUUID" : UUID("0d024925-e46c-472a-bf1a-13a8967e97c1"),
        "ok" : 1,
        "operationTime" : Timestamp(1593570389, 3),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1593570389, 3),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

Hinweis: Wenn die Sammlung nicht vorhanden ist, erstellen Sie sie wie folgt.

db.createCollection("geekFlareCollection")
{
        "ok" : 1,
        "operationTime" : Timestamp(1593570344, 4),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1593570344, 5),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

Schritt 9

Fügen Sie Daten in die Sammlung ein. Mongo-Protokolle beginnen zu wachsen und zeigen an, dass ein Balancer in Aktion ist und versucht, die Daten zwischen Shards auszugleichen.

Schritt 10

Der letzte Schritt besteht darin, den Status des Shardings zu überprüfen. Der Status kann überprüft werden, indem der folgende Befehl auf dem Mongos-Routenknoten ausgeführt wird.

Sharding-Status

Überprüfen Sie den Sharding-Status, indem Sie den folgenden Befehl auf dem Mongo-Routenknoten ausführen.

sh.status()

mongos> sh.status()
--- Sharding Status ---
  sharding version: {
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,
        "clusterId" : ObjectId("5ede66c22c3262378c706d21")
  }
  shards:
        {  "_id" : "rs1",  "host" : "rs1/localhost:27020,localhost:27021,localhost:27022",  "state" : 1 }
  active mongoses:
        "4.2.7" : 1
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  5
        Last reported error:  Could not find host matching read preference { mode: "primary" } for set rs1
        Time of Reported error:  Tue Jun 09 2020 15:25:03 GMT+0530 (India Standard Time)
        Migration Results for the last 24 hours:
                No recent migrations
  databases:
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }
                config.system.sessions
                        shard key: { "_id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                rs1     1024
                        too many chunks to print, use verbose if you want to force print
        {  "_id" : "geekFlareDB",  "primary" : "rs1",  "partitioned" : true,  "version" : {  "uuid" : UUID("a770da01-1900-401e-9f34-35ce595a5d54"),  "lastMod" : 1 } }
                geekFlareDB.geekFlareCol
                        shard key: { "key" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                rs1     1
                        { "key" : { "$minKey" : 1 } } -->> { "key" : { "$maxKey" : 1 } } on : rs1 Timestamp(1, 0)
                geekFlareDB.geekFlareCollection
                        shard key: { "product" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                rs1     1
                        { "product" : { "$minKey" : 1 } } -->> { "product" : { "$maxKey" : 1 } } on : rs1 Timestamp(1, 0)
        {  "_id" : "test",  "primary" : "rs1",  "partitioned" : false,  "version" : {  "uuid" : UUID("fbc00f03-b5b5-4d13-9d09-259d7fdb7289"),  "lastMod" : 1 } }

mongos>

Datenverteilung

Der Mongos-Router verteilt die Last auf Shards basierend auf dem Shard-Schlüssel und um Daten gleichmäßig zu verteilen; Balancer tritt in Aktion.

  So leeren Sie den Papierkorb nach X Tagen

Die Schlüsselkomponente zum Verteilen von Daten auf Shards sind

  • Ein Balancer spielt eine Rolle beim Ausgleichen der Teilmenge von Daten zwischen den Sharding-Knoten. Balancer wird ausgeführt, wenn der Mongos-Server beginnt, Lasten auf Shards zu verteilen. Nach dem Start verteilte Balancer die Daten gleichmäßiger. Um den Status des Balancers zu überprüfen, führen Sie sh.status() oder sh.getBalancerState() oder sh.isBalancerRunning() aus.
mongos> sh.isBalancerRunning()
true
mongos>

ODER

mongos> sh.getBalancerState()
true
mongos>

Nach dem Einfügen der Daten könnten wir eine Aktivität im Mongos-Daemon feststellen, die besagt, dass er einige Chunks für die spezifischen Shards verschiebt und so weiter, dh der Balancer wird in Aktion sein und versuchen, die Daten über die Shards hinweg auszugleichen. Das Ausführen von Balancer kann zu Leistungsproblemen führen; Daher wird empfohlen, den Balancer innerhalb einer bestimmten Zeit auszuführen Balancer-Fenster.

mongos> sh.status()
--- Sharding Status ---
  sharding version: {
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,
        "clusterId" : ObjectId("5efbeff98a8bbb2d27231674")
  }
  shards:
        {  "_id" : "rs1",  "host" : "rs1/127.0.0.1:27020,127.0.0.1:27021,127.0.0.1:27022",  "state" : 1 }
        {  "_id" : "rs2",  "host" : "rs2/127.0.0.1:27023,127.0.0.1:27024,127.0.0.1:27025",  "state" : 1 }
  active mongoses:
        "4.2.7" : 1
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  yes
        Failed balancer rounds in last 5 attempts:  5
        Last reported error:  Could not find host matching read preference { mode: "primary" } for set rs2
        Time of Reported error:  Wed Jul 01 2020 14:39:59 GMT+0530 (India Standard Time)
        Migration Results for the last 24 hours:
                1024 : Success
  databases:
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }
                config.system.sessions
                        shard key: { "_id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                rs2     1024
                        too many chunks to print, use verbose if you want to force print
        {  "_id" : "geekFlareDB",  "primary" : "rs2",  "partitioned" : true,  "version" : {  "uuid" : UUID("a8b8dc5c-85b0-4481-bda1-00e53f6f35cd"),  "lastMod" : 1 } }
                geekFlareDB.geekFlareCollection
                        shard key: { "key" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                rs2     1
                        { "key" : { "$minKey" : 1 } } -->> { "key" : { "$maxKey" : 1 } } on : rs2 Timestamp(1, 0)
        {  "_id" : "test",  "primary" : "rs2",  "partitioned" : false,  "version" : {  "uuid" : UUID("a28d7504-1596-460e-9e09-0bdc6450028f"),  "lastMod" : 1 } }

mongos>
  • Shard Key bestimmt die Logik zum Verteilen von Dokumenten der Shard-Sammlung auf die Shards. Der Shard-Schlüssel kann ein indiziertes Feld oder ein indiziertes zusammengesetztes Feld sein, das in allen einzufügenden Dokumenten der Sammlung vorhanden sein muss. Daten werden in Chunks partitioniert, und jeder Chunk wird dem bereichsbasierten Shard-Schlüssel zugeordnet. Anhand der Bereichsabfrage entscheidet der Router, welcher Shard den Chunk speichert.

Shard Key kann unter Berücksichtigung von fünf Eigenschaften ausgewählt werden:

  • Kardinalität
  • Verteilung schreiben
  • Verteilung lesen
  • Ausrichtung lesen
  • Lokal lesen

Ein idealer Shard-Schlüssel sorgt dafür, dass MongoDB die Last gleichmäßig auf alle Shards verteilt. Die Wahl eines guten Shard Keys ist äußerst wichtig.

Bild: MongoDB

Entfernen des Shard-Knotens

Vor dem Entfernen von Shards aus dem Cluster muss der Benutzer sicherstellen, dass die Daten sicher auf die verbleibenden Shards migriert werden. MongoDB sorgt dafür, dass Daten sicher auf andere Shard-Knoten übertragen werden, bevor der erforderliche Shard-Knoten entfernt wird.

Führen Sie den folgenden Befehl aus, um den erforderlichen Shard zu entfernen.

Schritt 1

Zuerst müssen wir den Hostnamen des zu entfernenden Shards bestimmen. Der folgende Befehl listet alle im Cluster vorhandenen Shards zusammen mit dem Zustand des Shards auf.

db.adminCommand( { listShards: 1 } )

mongos> db.adminCommand( { listShards: 1 } )
{
        "shards" : [
                {
                        "_id" : "rs1",
                        "host" : "rs1/127.0.0.1:27020,127.0.0.1:27021,127.0.0.1:27022",
                        "state" : 1
                },
                {
                        "_id" : "rs2",
                        "host" : "rs2/127.0.0.1:27023,127.0.0.1:27024,127.0.0.1:27025",
                        "state" : 1
                }
        ],
        "ok" : 1,
        "operationTime" : Timestamp(1593572866, 15),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1593572866, 15),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

Schritt 2

Geben Sie den folgenden Befehl aus, um den erforderlichen Shard aus dem Cluster zu entfernen. Nach der Ausgabe kümmert sich der Balancer um das Entfernen von Chunks aus dem Draining-Shard-Knoten und gleicht dann die Verteilung der verbleibenden Chunks auf die restlichen Shard-Knoten aus.

db.adminCommand( { removeShard: „shardedReplicaNodes“ } )

mongos> db.adminCommand( { removeShard: "rs1/127.0.0.1:27020,127.0.0.1:27021,127.0.0.1:27022" } )
{
        "msg" : "draining started successfully",
        "state" : "started",
        "shard" : "rs1",
        "note" : "you need to drop or movePrimary these databases",
        "dbsToMove" : [ ],
        "ok" : 1,
        "operationTime" : Timestamp(1593572385, 2),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1593572385, 2),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

Schritt 3

Um den Status des leeren Shards zu überprüfen, geben Sie denselben Befehl erneut aus.

db.adminCommand( { removeShard: „rs1/127.0.0.1:27020,127.0.0.1:27021,127.0.0.1:27022“ } )

Wir müssen warten, bis das Löschen der Daten abgeschlossen ist. msg- und state-Felder zeigen wie folgt, ob das Löschen der Daten abgeschlossen ist oder nicht

"msg" : "draining ongoing",
"state" : "ongoing",

Wir können den Status auch mit dem Befehl sh.status() überprüfen. Einmal entfernte Sharding-Knoten werden nicht in der Ausgabe wiedergegeben. Wenn das Draining jedoch andauert, wird der Shard-Knoten mit dem Draining-Status „true“ angezeigt.

Schritt 4

Überprüfen Sie weiterhin den Status des Entleerens mit demselben obigen Befehl, bis der erforderliche Shard vollständig entfernt ist.
Sobald der Vorgang abgeschlossen ist, gibt die Ausgabe des Befehls die Nachricht und den Status als abgeschlossen wieder.

"msg" : "removeshard completed successfully",
"state" : "completed",
"shard" : "rs1",
"ok" : 1,

Schritt 5

Schließlich müssen wir die verbleibenden Shards im Cluster überprüfen. Um den Status zu überprüfen, geben Sie sh.status() oder db.adminCommand( { listShards: 1 } ) ein

mongos> db.adminCommand( { listShards: 1 } )
{
        "shards" : [
                {
                        "_id" : "rs2",
                        "host" : "rs2/127.0.0.1:27023,127.0.0.1:27024,127.0.0.1:27025",
                        "state" : 1
                }
        ],
        "ok" : 1,
        "operationTime" : Timestamp(1593575215, 3),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1593575215, 3),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

Hier können wir sehen, dass der entfernte Shard nicht mehr in der Liste der Shards vorhanden ist.

Vorteile von Sharding gegenüber Replikation

  • Bei der Replikation verarbeitet der primäre Knoten alle Schreibvorgänge, während sekundäre Server Sicherungskopien verwalten oder schreibgeschützte Vorgänge ausführen müssen. Aber beim Sharding zusammen mit Replikat-Sets wird die Last auf eine Anzahl von Servern verteilt.
  • Ein einzelner Replikatsatz ist auf 12 Knoten begrenzt, aber es gibt keine Beschränkung hinsichtlich der Anzahl der Shards.
  • Die Replikation erfordert High-End-Hardware oder vertikale Skalierung für die Handhabung großer Datasets, was im Vergleich zum Hinzufügen zusätzlicher Server beim Sharding zu teuer ist.
  • Bei der Replikation kann die Leseleistung durch Hinzufügen weiterer Slave-/Sekundärserver verbessert werden, während beim Sharding sowohl die Lese- als auch die Schreibleistung durch Hinzufügen weiterer Shard-Knoten verbessert werden.

Sharding-Beschränkung

  • Der Sharded-Cluster unterstützt keine eindeutige Indizierung über die Shards hinweg, bis dem eindeutigen Index der vollständige Shard-Schlüssel vorangestellt wird.
  • Alle Aktualisierungsvorgänge für die Sharding-Erfassung entweder für ein oder mehrere Dokumente müssen den Sharding-Schlüssel oder das _id-Feld in der Abfrage enthalten.
  • Sammlungen können fragmentiert werden, wenn ihre Größe den angegebenen Schwellenwert nicht überschreitet. Dieser Schwellenwert kann auf der Grundlage der durchschnittlichen Größe aller Shard-Schlüssel und der konfigurierten Chunk-Größe geschätzt werden.
  • Sharding umfasst Betriebsgrenzen für die maximale Sammlungsgröße oder die Anzahl der Splits.
  • Die Auswahl der falschen Shard-Schlüssel führt zu Leistungseinbußen.

Fazit

MongoDB bietet integriertes Sharding, um eine große Datenbank zu implementieren, ohne die Leistung zu beeinträchtigen. Ich hoffe, das Obige hilft Ihnen beim Einrichten von MongoDB-Sharding. Als Nächstes möchten Sie sich vielleicht mit einigen der häufig verwendeten MongoDB-Befehle vertraut machen.