Sdílení je proces rozdělování velkého rozsahu datových sad na kusy menších datových sad napříč několika instancemi MongoDB v distribuovaném prostředí.
Table of Contents
Co je Sharding?
MongoDB sharding nám poskytuje škálovatelné řešení pro ukládání velkého množství dat mezi určitým počtem serverů namísto ukládání na jeden server.
Z praktického hlediska není možné ukládat exponenciálně rostoucí data na jednom počítači. Dotazování na velké množství dat uložených na jediném serveru by mohlo vést k vysokému využití zdrojů a nemusí poskytovat uspokojivou propustnost čtení a zápisu.
V zásadě existují dva typy metod škálování, které umožňují provádět rostoucí data se systémem:
Vertikální škálování pracuje se zvýšením výkonu jednoho serveru přidáním výkonnějších procesorů, upgradem paměti RAM nebo přidáním více místa na disku do systému. Existují však možné důsledky použití vertikálního škálování v praktických případech použití se stávající technologií a hardwarovými konfiguracemi.
Horizontální škálování pracuje s přidáním dalších serverů a rozložením zátěže na více serverů. Vzhledem k tomu, že každý stroj bude zpracovávat podmnožinu celé datové sady, poskytuje lepší efektivitu a nákladově efektivní řešení než nasazení špičkového hardwaru. Vyžaduje to však další údržbu složité infrastruktury s velkým počtem serverů.
Mongo DB sharding funguje na technice horizontálního škálování.
Sdílení součástí
K dosažení shardingu v MongoDB jsou vyžadovány následující komponenty:
Shard je instance Mongo pro zpracování podmnožiny původních dat. Střepy musí být nasazeny v sadě replik.
Mongos je instance Mongo a funguje jako rozhraní mezi klientskou aplikací a sdíleným clusterem. Funguje jako směrovač dotazů na shardy.
Config Server je instance Mongo, která ukládá informace o metadatech a podrobnosti o konfiguraci clusteru. MongoDB vyžaduje, aby byl konfigurační server nasazen jako sada replik.
Sharding Architecture
MongoDB cluster se skládá z řady sad replik.
Každá sada replik se skládá z minimálně 3 nebo více instancí mongo. Sdílený cluster se může skládat z několika instancí fragmentů mongo a každá instance fragmentu funguje v sadě replik fragmentů. Aplikace komunikuje s Mongos, který zase komunikuje se shardy. Proto ve Sharding aplikace nikdy nekomunikují přímo s uzly fragmentů. Směrovač dotazů distribuuje podmnožiny dat mezi uzly fragmentů na základě klíče shardu.
Implementace Sharding
Postupujte podle níže uvedených kroků pro shardování
Krok 1
- Spusťte konfigurační server v sadě replik a povolte replikaci mezi nimi.
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
Krok 2
- Inicializujte sadu replik na jednom z konfiguračních serverů.
rs.initiate( { _id : “rs0”, configsvr: true, členové: [ { _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) }
Krok 3
- Spusťte sharding serverů v sadě replik a povolte replikaci mezi nimi.
mongod –shardsvr –port 27020 –replSet rs1 –dbpath C:data4 –bind_ip localhost
mongod –shardsvr –port 27021 –replSet rs1 –dbpath C:data5 –bind_ip localhost
mongod –shardsvr –port 27022 –replSet rs1 –dbpath C:data6 –bind_ip localhost
MongoDB inicializuje první sharding server jako primární, aby přesunul použití primárního sharding serveru movePrimary metoda.
Krok 4
- Inicializujte sadu replik na jednom ze sdílených serverů.
rs.initiate( { _id : “rs0”, členové: [ { _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) }
Krok 5
- Spusťte manga pro střepový shluk
mongos –port 40000 –configdb rs0/localhost:27019,localhost:27018, localhost:27017
Krok 6
- Připojte server mongo route
mongo – port 40000
- Nyní přidejte sharding servery.
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) } } }
Krok 7
- Na mongo shellu povolte sharding na DB a kolekce.
- Povolit sdílení na 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) } } }
Krok 8
- Chcete-li fragmentovat sběrný klíč (popsaný dále v tomto článku), je vyžadován.
Syntaxe: 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) } } }
Všimněte si, že pokud kolekce neexistuje, vytvořte ji následovně.
db.createCollection("geekFlareCollection") { "ok" : 1, "operationTime" : Timestamp(1593570344, 4), "$clusterTime" : { "clusterTime" : Timestamp(1593570344, 5), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } }
Krok 9
Vložte data do kolekce. Protokoly Mongo začnou přibývat a indikují, že balancer je v akci a snaží se vyvážit data mezi úlomky.
Krok 10
Posledním krokem je kontrola stavu shardingu. Stav lze zkontrolovat spuštěním níže uvedeného příkazu na uzlu trasy Mongos.
Stav sdílení
Zkontrolujte stav shardingu spuštěním příkazu níže v uzlu trasy mongo.
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>
Distribuce dat
Router Mongos rozděluje zátěž mezi shardy na základě shard klíče a rovnoměrně distribuuje data; vyvažovač přichází do činnosti.
Klíčovou složkou pro distribuci dat mezi shardy jsou
- Balancér hraje roli při vyvažování podmnožiny dat mezi rozštěpenými uzly. Balancer se spustí, když server Mongos začne rozdělovat zatížení mezi fragmenty. Po spuštění Balancer distribuoval data rovnoměrněji. Chcete-li zkontrolovat stav balanceru, spusťte sh.status() nebo sh.getBalancerState() nebo
sh.isBalancerRunning().
mongos> sh.isBalancerRunning() true mongos>
NEBO
mongos> sh.getBalancerState() true mongos>
Po vložení dat jsme si mohli všimnout nějaké aktivity v démonu Mongos, který říká, že přesouvá nějaké kousky pro konkrétní shardy a tak dále, tj. balancer se bude snažit vyvážit data napříč shardy. Spuštění balanceru by mohlo vést k problémům s výkonem; proto se doporučuje spustit vyvažovač v určitém rozsahu vyvažovací okno.
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 určuje logiku distribuce dokumentů sdílené kolekce mezi fragmenty. Sdílený klíč může být indexované pole nebo indexované složené pole, které musí být přítomno ve všech dokumentech kolekce, která má být vložena. Data budou rozdělena do bloků a každý blok bude přidružen k datovému klíči založenému na rozsahu. Na základě dotazu na rozsah router rozhodne, do kterého shardu bude chunk uložen.
Shard Key lze vybrat zvážením pěti vlastností:
- Kardinalita
- Napište distribuci
- Přečtěte si distribuci
- Číst cílení
- Přečtěte si lokalitu
Ideální shard klíč umožňuje MongoDB rovnoměrně rozložit zátěž mezi všechny shardy. Výběr dobrého klíče je nesmírně důležitý.
Obrázek: MongoDB
Odstranění uzlu úlomku
Před odstraněním shardů z clusteru je uživatel povinen zajistit bezpečnou migraci dat na zbývající shardy. MongoDB se stará o bezpečné vypouštění dat do jiných uzlů shardů před odstraněním požadovaného uzlu shardu.
Spuštěním níže uvedeného příkazu odstraňte požadovaný fragment.
Krok 1
Nejprve musíme určit název hostitele fragmentu, který má být odstraněn. Níže uvedený příkaz zobrazí seznam všech úlomků přítomných v clusteru spolu se stavem úlomku.
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) } } }
Krok 2
Vydáním níže uvedeného příkazu odeberte požadovaný fragment z clusteru. Po vydání se balancer postará o odstranění kousků z odvodňovacího uzlu střepů a poté vyrovná distribuci zbývajících kousků mezi ostatní uzly střepů.
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) } } }
Krok 3
Chcete-li zkontrolovat stav odvodňovacího úlomku, zadejte znovu stejný příkaz.
db.adminCommand( { removeShard: “rs1/127.0.0.1:27020,127.0.0.1:27021,127.0.0.1:27022” } )
Musíme počkat, až bude vyčerpání dat dokončeno. Pole msg a state budou ukazovat, zda bylo vypouštění dat dokončeno nebo ne, následovně
"msg" : "draining ongoing", "state" : "ongoing",
Stav můžeme také zkontrolovat příkazem sh.status(). Odstraněný uzel se ve výstupu neprojeví. Pokud však bude vypouštění probíhat, bude u střeženého uzlu uveden stav vypouštění jako pravdivý.
Krok 4
Pokračujte v kontrole stavu vypouštění stejným výše uvedeným příkazem, dokud nebude požadovaný úlomek zcela odstraněn.
Po dokončení bude výstup příkazu odrážet zprávu a stav jako dokončený.
"msg" : "removeshard completed successfully", "state" : "completed", "shard" : "rs1", "ok" : 1,
Krok 5
Nakonec musíme zkontrolovat zbývající úlomky ve shluku. Chcete-li zkontrolovat stav, zadejte sh.status() nebo 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) } } }
Zde vidíme, že odstraněný střep již není přítomen v seznamu střepů.
Výhody sdílení přes replikaci
- Při replikaci primární uzel zpracovává všechny operace zápisu, zatímco sekundární servery musí udržovat záložní kopie nebo obsluhovat operace pouze pro čtení. Ale při shardování spolu se sadami replik se zátěž rozdělí mezi počet serverů.
- Jedna sada replik je omezena na 12 uzlů, ale počet střepů není nijak omezen.
- Replikace vyžaduje špičkový hardware nebo škálování vertikál pro manipulaci s velkými datovými sadami, což je příliš nákladné ve srovnání s přidáváním dalších serverů ve shardingu.
- Při replikaci lze výkon čtení zvýšit přidáním více podřízených/sekundárních serverů, zatímco při shardingu bude výkon čtení i zápisu zvýšen přidáním více uzlů shardů.
Omezení sdílení
- Cluster Sharded nepodporuje jedinečné indexování napříč fragmenty, dokud jedinečný index není opatřen předponou úplným klíčem fragmentu.
- Všechny aktualizační operace pro sdílenou kolekci na jednom nebo více dokumentech musí obsahovat sdílený klíč nebo pole _id v dotazu.
- Kolekce lze rozdělit, pokud jejich velikost nepřesahuje zadanou prahovou hodnotu. Tento práh lze odhadnout na základě průměrné velikosti všech fragmentů klíčů a nakonfigurované velikosti bloků.
- Sdílení zahrnuje provozní limity maximální velikosti sbírky nebo počtu rozdělení.
- Výběr nesprávných klíčů zlomku má dopad na výkon.
Závěr
MongoDB nabízí vestavěné sharding pro implementaci velké databáze bez snížení výkonu. Doufám, že výše uvedené vám pomůže nastavit sharding MongoDB. Dále se možná budete chtít seznámit s některými běžně používanými příkazy MongoDB.