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

Sharding är en process för att dela upp den stora skalan av datamängder i en bit av mindre datamängder över flera MongoDB-instanser i en distribuerad miljö.

Vad är Sharding?

MongoDB sharding ger oss en skalbar lösning för att lagra en stor mängd data bland antalet servrar snarare än att lagra på en enda server.

Rent praktiskt är det inte möjligt att lagra exponentiellt växande data på en enda maskin. Att söka efter en enorm mängd data som lagras på en enda server kan leda till högt resursutnyttjande och kanske inte ge tillfredsställande läs- och skrivkapacitet.

I grund och botten finns det två typer av skalningsmetoder som finns för att genomföra växande data med systemet:

Vertical Scaling arbetar med att förbättra prestanda för en enda server genom att lägga till kraftfullare processorer, uppgradera RAM eller lägga till mer diskutrymme till systemet. Men det finns möjliga konsekvenser av att tillämpa vertikal skalning i praktiska användningsfall med befintlig teknik och hårdvarukonfigurationer.

Horisontell skalning fungerar med att lägga till fler servrar och fördela belastningen på flera servrar. Eftersom varje maskin kommer att hantera delmängden av hela datamängden, ger den bättre effektivitet och kostnadseffektiv lösning snarare än att distribuera den avancerade hårdvaran. Men det kräver ytterligare underhåll av komplex infrastruktur med ett stort antal servrar.

Mongo DB skärning fungerar på horisontell skalningsteknik.

Skärva komponenter

För att uppnå skärning i MongoDB krävs följande komponenter:

Shard är en Mongo-instans för att hantera en delmängd av originaldata. Skärvor måste distribueras i replikuppsättningen.

Mongos är en Mongo-instans och fungerar som ett gränssnitt mellan en klientapplikation och ett fragmenterat kluster. Det fungerar som en frågerouter till skärvor.

Config Server är en Mongo-instans som lagrar metadatainformation och konfigurationsdetaljer för klustret. MongoDB kräver att konfigurationsservern distribueras som en replikuppsättning.

Sharding arkitektur

MongoDB-klustret består av ett antal replikuppsättningar.

Varje replikuppsättning består av minst 3 eller fler mongo-instanser. Ett sharded kluster kan bestå av flera mongo shards-instanser, och varje shard-instans fungerar inom en shard-replikuppsättning. Applikationen interagerar med Mongos, som i sin tur kommunicerar med skärvor. Därför interagerar applikationer aldrig direkt med shardnoder i Sharding. Frågeroutern distribuerar delmängderna av data mellan shardsnoder baserat på shardnyckeln.

Sharding Implementering

Följ stegen nedan för skärning

Steg 1

  • Starta konfigurationsservern i replikuppsättningen och aktivera replikering mellan dem.

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.

rs.initiate( { _id : ”rs0”, configsvr: true, medlemmar: [   { _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)
}

Steg 3

  • Börja dela servrar i replikuppsättningen och aktivera replikering mellan dem.

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 shardingservern som primär, för att flytta den primära shardingserverns användning flyttaPrimär metod.

Steg 4

  • Initiera replikuppsättningen på en av de sönderdelade servrarna.

rs.initiate( { _id : ”rs0”, medlemmar: [   { _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)
}

Steg 5

  • Starta mangon för den sönderdelade klasen

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

Steg 6

  • Anslut mongo route-servern

mongo –port 40000

  • Lägg nu till skärningsservrar.

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

Steg 7

  • På mongo-skal möjliggör sharding på DB och samlingar.
  • Aktivera sönderdelning på DB

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

Steg 8

  • För att skära krävs en samlingsnyckel (beskrivs senare i den här artikeln).

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

Observera om samlingen inte finns, skapa enligt följande.

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

Steg 9

Infoga data i samlingen. Mongologgar kommer att börja växa, och indikerar att en balanserare är i aktion och försöker balansera data mellan skärvor.

Steg 10

Det sista steget är att kontrollera klippningens status. Status kan kontrolleras genom att köra kommandot nedan på Mongos ruttnod.

Delningsstatus

Kontrollera sönderdelningsstatus genom att köra under kommandot på mongo-ruttnoden.

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 belastningen mellan shards baserat på shard-nyckeln och för att jämnt fördela data; balancer träder i kraft.

Nyckelkomponenten för att distribuera data mellan skärvor är

  • En balanserare spelar en roll för att balansera delmängden av data bland de sönderdelade noderna. Balancer körs när Mongos server börjar fördela belastningar mellan skärvor. När den väl startat fördelade Balancer data mer jämnt. För att kontrollera tillståndet för balancer, kör sh.status() eller sh.getBalancerState() ellersh.isBalancerRunning().
mongos> sh.isBalancerRunning()
true
mongos>

ELLER

mongos> sh.getBalancerState()
true
mongos>

Efter att ha infogat data kunde vi märka viss aktivitet i Mongos-demonen som säger att den flyttar några bitar för de specifika skärvorna och så vidare, dvs balanseraren kommer att vara i aktion och försöka balansera data över skärvorna. Att köra balancer kan leda till prestationsproblem; därför föreslås det att köra balanseringen inom en viss 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 Key bestämmer logiken för att distribuera dokument med fragmenterad insamling bland skärvorna. Shard-nyckel kan vara ett indexerat fält eller ett indexerat sammansatt fält som måste finnas i alla dokument i samlingen som ska infogas. Data kommer att delas upp i bitar och varje bit kommer att associeras med den intervallbaserade shard-nyckeln. På basis av intervallfrågan kommer routern att bestämma vilken shard som ska lagra biten.

Shard Key kan väljas genom att överväga fem egenskaper:

  • Kardinalitet
  • Skriv distribution
  • Läs distribution
  • Läs inriktning
  • Läs ort

En idealisk skärvnyckel gör att MongoDB fördelar belastningen jämnt mellan alla skärvor. Att välja en bra skärvnyckel är extremt viktigt.

Bild: MongoDB

Ta bort shardnoden

Innan du tar bort shards från klustret måste användaren säkerställa säker migrering av data till återstående shards. MongoDB tar hand om att säkert dränera data till andra shardsnoder innan den nödvändiga shardnoden tas bort.

Kör kommandot nedan för att ta bort den nödvändiga skärpan.

Steg 1

Först måste vi bestämma värdnamnet för skärvan som ska tas bort. Kommandot nedan kommer att lista alla skärvor som finns i klustret tillsammans med skärvans tillstånd.

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

Ge kommandot nedan för att ta bort den nödvändiga skärpan från klustret. När den väl har utfärdats tar balanseringsenheten bort bitar från dränerande skärvnod och balanserar sedan fördelningen av återstående bitar bland resten av skärvnoderna.

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 dränerande skärpan, utfärda samma kommando igen.

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

Vi måste vänta tills tömningen av data är klar. msg och state-fält kommer att visa om tömning av data har slutförts eller inte, enligt följande

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

Vi kan också kontrollera status med kommandot sh.status(). När den väl har tagits bort kommer den fragmenterade noden inte att återspeglas i utdata. Men om dräneringen kommer att pågå kommer den sönderdelade noden att ha dräneringsstatus som sann.

Steg 4

Fortsätt att kontrollera tömningens status med samma kommando ovan, tills den nödvändiga skärpan har tagits bort helt.
När det är klart, kommer utdata från kommandot att återspegla meddelandet och status som slutfört.

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

Steg 5

Slutligen måste vi kontrollera de återstående skärvorna i klustret. För att kontrollera status anger du sh.status() eller db.adminCommand( { listShards: 1 } )

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

Här kan vi se att den borttagna skärpan inte längre finns i listan över skärvor.

Fördelarna med Sharding framför replikering

  • Vid replikering hanterar den primära noden alla skrivoperationer, medan sekundära servrar krävs för att underhålla säkerhetskopior eller betjäna skrivskyddade operationer. Men vid skärning tillsammans med replikuppsättningar fördelas belastningen mellan antalet servrar.
  • En enkel replikuppsättning är begränsad till 12 noder, men det finns ingen begränsning på antalet skärvor.
  • Replikering kräver avancerad hårdvara eller vertikal skalning för att hantera stora datamängder, vilket är för dyrt jämfört med att lägga till ytterligare servrar i sharding.
  • Vid replikering kan läsprestandan förbättras genom att lägga till fler slav-/sekundära servrar, medan både läs- och skrivprestandan vid sharding kommer att förbättras genom att lägga till fler shards-noder.

Skärningsbegränsning

  • Sharded-klustret stöder inte unik indexering över skärvorna förrän det unika indexet har prefixet fullständig skärvnyckel.
  • Alla uppdateringsåtgärder för fragmenterad insamling, antingen på ett eller flera dokument, måste innehålla fältet sharded key eller _id i frågan.
  • Samlingar kan delas om deras storlek inte överstiger den angivna tröskeln. Denna tröskel kan uppskattas på basis av den genomsnittliga storleken på alla shard-nycklar och konfigurerad storlek på bitar.
  • Skärning består av operativa begränsningar för max uppsamlingsstorlek eller antal delar.
  • Att välja fel skärvnycklar för att leda till prestandaimplikationer.

Slutsats

MongoDB erbjuder inbyggd skärning för att implementera en stor databas utan att kompromissa med prestandan. Jag hoppas att ovanstående hjälper dig att ställa in MongoDB-sharding. Därefter kanske du vill bekanta dig med några av de vanligaste MongoDB-kommandona.