MongoDB Sharding: Steg-för-steg praktisk guide

By rik

Introduktion till Sharding i MongoDB

Sharding är en metod för att segmentera stora datamängder i hanterbara mindre delar, fördelade över flera MongoDB-instanser i en distribuerad miljö. Det möjliggör att hantera och lagra stora mängder data mer effektivt genom att sprida lasten över flera maskiner.

Vad innebär Sharding?

MongoDB sharding erbjuder en skalbar lösning för att hantera omfattande datamängder. Istället för att lagra all information på en enda server, distribueras datan över flera servrar, vilket ger en mer robust och effektiv lösning.

Att lagra ständigt ökande datamängder på en enskild maskin är i praktiken ohållbart. Sökningar i enorma datamängder på en enda server kan leda till hög resursanvändning och otillfredsställande prestanda för både läs- och skrivoperationer.

Det finns huvudsakligen två metoder för att skala system för att hantera växande datamängder:

Vertikal skalning innebär att förbättra prestandan på en enskild server genom att uppgradera processorer, RAM eller diskutrymme. Denna metod kan dock ha sina begränsningar i praktiska användningsfall med dagens teknik och hårdvarukonfigurationer.

Horisontell skalning innebär att lägga till fler servrar och fördela belastningen över dessa. Varje maskin hanterar en delmängd av den totala datan, vilket leder till bättre effektivitet och kostnadseffektivitet. Det kräver dock mer underhåll av en komplex infrastruktur med ett stort antal servrar. Mongo DB sharding bygger på principen om horisontell skalning.

Komponenter i Sharding

För att implementera sharding i MongoDB krävs följande nyckelkomponenter:

Shard: En instans av MongoDB som lagrar en delmängd av originaldatan. Shards distribueras inom replikuppsättningar för att säkerställa redundans.

Mongos: En Mongo-instans som fungerar som gränssnitt mellan klientapplikationer och det fragmenterade klustret. Den fungerar som en frågerouter till rätt shard.

Config Server: En Mongo-instans som lagrar metadata och konfigurationsinformation för hela klustret. Konfigurationsservern måste också distribueras som en replikuppsättning.

Sharding-arkitektur

Ett MongoDB-kluster för sharding består av flera replikuppsättningar.

Varje replikuppsättning består av minst tre eller fler MongoDB-instanser. Ett shardat kluster kan innehålla många shards, där varje shard fungerar inom sin egen replikuppsättning. Applikationer kommunicerar med Mongos, som sedan interagerar med rätt shards. Applikationer interagerar alltså aldrig direkt med shard-noderna. Frågeroutern distribuerar data baserat på den valda shardnyckeln.

Steg-för-steg-implementering av Sharding

Här följer en steg-för-steg-guide för att implementera sharding i MongoDB:

Steg 1:

  • Starta konfigurationsservern som en replikuppsättning och aktivera replikering.

Exempelkommandon:

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

Steg 2:

  • Initiera replikuppsättningen på en av konfigurationsservrarna.

Exempelkommando:

rs.initiate( { _id : "rs0", configsvr: true, members: [ { _id: 0, host: "IP:27017" }, { _id: 1, host: "IP:27018" }, { _id: 2, host: "IP:27019" } ] })

Steg 3:

  • Starta shard-servrarna i sina replikuppsättningar och aktivera replikering.

Exempelkommandon:

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

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

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

MongoDB initierar den första shard-servern som primär, om du behöver flytta den primära shard-servern kan du använda movePrimary-metoden.

Steg 4:

  • Initiera replikuppsättningen på en av de shardservrarna.

Exempelkommando:

rs.initiate( { _id : "rs0", members: [ { _id: 0, host: "IP:27020" }, { _id: 1, host: "IP:27021" }, { _id: 2, host: "IP:27022" } ] })

Steg 5:

  • Starta Mongos-routern för det shardade klustret.

Exempelkommando:

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

Steg 6:

  • Anslut till Mongos-routern.

Exempelkommando:

mongo --port 40000

  • Lägg nu till shard-servrarna i klustret.

Exempelkommando:

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

Steg 7:

  • Aktivera sharding på databasen och samlingar via mongo-skalet.
  • Aktivera sharding på önskad databas.

Exempelkommando:

sh.enableSharding("geekFlareDB")

Steg 8:

  • För att sharda en samling krävs en shardnyckel.

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

Exempelkommando:

sh.shardCollection("geekFlareDB.geekFlareCollection", { "key" : 1 } )

Om samlingen inte finns, skapa den med:

db.createCollection("geekFlareCollection")

Steg 9:

Infoga data i samlingen. MongoDB loggar bör visa aktivitet, vilket indikerar att balancer försöker jämna ut datan mellan sharderna.

Steg 10:

Kontrollera shardingens status genom att köra sh.status() på Mongos routern.

Kontroll av Sharding Status

Använd följande kommando för att kontrollera sharding-statusen.

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>
    

Datadistribution

Mongos-routern fördelar lasten mellan shards baserat på shard-nyckeln. En balanserare ser till att data distribueras jämnt.

Nyckelkomponenterna för datadistribution är:

  • Balancer: Balanserar datamängder över shard-noderna. Balancer körs automatiskt när Mongos-servern börjar fördela lasten. För att kontrollera balancerns status, använd sh.status(), sh.getBalancerState() eller sh.isBalancerRunning().
    mongos> sh.isBalancerRunning()
    true
    mongos>
      

Eller:

    mongos> sh.getBalancerState()
    true
    mongos>
        

Efter datainmatning kan aktiviteter ses i Mongos-demonen som indikerar att data flyttas mellan shards. Balancern försöker kontinuerligt att jämna ut data. Eftersom detta kan påverka prestandan är det rekommenderat att köra balancer inom ett specifikt balanseringsfönster.

    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-nyckel: Bestämmer hur dokument distribueras i den shardade samlingen. Den kan vara ett indexerat fält eller ett sammansatt indexerat fält som måste finnas i alla dokument i samlingen. Data delas upp i bitar och varje bit är associerad med en shardnyckel. Baserat på shardnyckelns värde bestämmer routern vilken shard som ska lagra biten.

Shard-nycklar väljs med följande egenskaper i åtanke:

  • Kardinalitet
  • Skrivdistribution
  • Läsdistribution
  • Läsriktning
  • Läs-lokalitet

En idealisk shard-nyckel bör möjliggöra en jämn fördelning av lasten mellan sharderna. Valet av shard-nyckel är kritiskt för prestanda.

Bildkälla: MongoDB

Ta bort Shard-nod

Innan du tar bort en shard från klustret måste du säkerställa att all data har migrerats till de återstående sharderna. MongoDB sköter automatiskt säker migrering av data.

Följ dessa steg för att ta bort en shard:

Steg 1:

Först måste du identifiera värdnamnet på den shard som ska tas bort. Kommandot nedan listar alla shards i klustret med deras status.

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)
                }
        }
    }
    

Steg 2:

Använd kommandot nedan för att ta bort shard från klustret. Balancer kommer då att flytta bitar från den shard-nod som ska tas bort och jämna ut distributionen bland de återstående shard-noderna.

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)
                }
        }
    }
    

Steg 3:

För att kontrollera statusen för den shard som töms, kör samma kommando igen.

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

Vänta tills tömningen är klar. Fältet msg och state kommer att visa om tömningen är slutförd eller inte.

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

Status kan också kontrolleras med kommandot sh.status(). När shard-noden har tagits bort syns den inte längre i utdata. Under tömning kommer den shardade noden att ha dräneringsstatus som true.

Steg 4:

Fortsätt kontrollera tömningsstatusen med samma kommando tills den nödvändiga shard-noden är borttagen. När det är klart, kommer utdata att visa meddelandet och status completed.

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

Steg 5:

Kontrollera de återstående sharderna i klustret. Använd sh.status() eller db.adminCommand( { listShards: 1 } ) för att kontrollera statusen.

    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)
                }
        }
    }
    

Den borttagna sharden ska nu vara borta från listan över shards.

Fördelar med Sharding jämfört med Replikering

  • Vid replikering hanterar primära noden alla skrivoperationer medan sekundära servrar hanterar säkerhetskopiering eller skrivskyddade operationer. Med sharding, i kombination med replikuppsättningar, fördelas lasten mellan flera servrar.
  • En enkel replikuppsättning är begränsad till 12 noder men antalet shards är obegränsat.
  • Replikering kräver ofta avancerad hårdvara eller vertikal skalning för att hantera stora datamängder, vilket är kostsamt jämfört med att lägga till ytterligare servrar med sharding.
  • Med replikering kan läsprestandan ökas genom att lägga till fler sekundära servrar, medan både läs- och skrivprestandan förbättras med sharding genom att lägga till fler shard-noder.

Begränsningar med Sharding

  • Sharded kluster stöder inte unika index över shards om det inte finns en prefixad unik shardnyckel.
  • Alla uppdateringsoperationer på en shardad samling måste inkludera shardnyckeln eller ”_id” i frågan.
  • Samlingar kan endast delas om storleken inte överskrider en förutbestämd gräns.
  • Sharding har operativa begränsningar för maximal samlingsstorlek eller antal delar.
  • Felaktigt val av shard-nyckel kan leda till prestandaproblem.

Sammanfattning

MongoDB erbjuder inbyggt stöd för sharding för att implementera stora databaser utan att kompromissa med prestandan. Förhoppningsvis hjälper ovanstående information att förstå hur du ställer in MongoDB sharding. Därefter kan det vara bra att bekanta sig med vanliga MongoDB-kommandon.