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()
ellersh.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.