English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Prefazione
In MongoDB (versione 3.2.9), il cluster sharded (cluster sharded) è un metodo di espansione orizzontale della capacità di sistema del database, che può memorizzare il set di dati distribuitamente su diversi shard (shard), ciascuno dei quali memorizza solo una parte del set di dati. MongoDB garantisce che non ci siano dati duplicati tra i vari shard, e la somma dei dati memorizzati in tutti i shard rappresenta l'intero set di dati. La memorizzazione distribuita del set di dati permette di distribuire il carico su più shard, ciascuno dei quali è responsabile della lettura e scrittura di una parte dei dati, sfruttando al massimo le risorse di sistema di ciascun shard e aumentando la capacità di throughput del sistema di database.
Il set di dati viene diviso in chunk (pezzi di dati), ciascuno dei quali contiene più doc, e i chunk vengono memorizzati in modo distribuito nel cluster di shard. MongoDB è responsabile di tracciare l'informazione sulla distribuzione dei chunk sui shard, che indica quali chunk vengono memorizzati su quale shard, detta metadata del shard, e viene memorizzata nel database config sul server di configurazione. Di solito si utilizzano 3 server di configurazione, e tutti i database config nei server di configurazione devono essere identici. Attraverso mongos è possibile accedere direttamente al database config per visualizzare i metadata dei shard; mongo shell fornisce la funzione di assistenza sh, che permette di visualizzare in modo sicuro le informazioni sui metadata del cluster di shard.
Per ogni shard, la query restituirà solo una sottosquadra di dati della collection nella shard corrente, non l'intero set di dati. L'applicazione deve connettersi solo a mongos e eseguire operazioni di lettura e scrittura su di esso, mongos routerà automaticamente le richieste di lettura e scrittura ai shard appropriati. MongoDB nasconde la realizzazione sottostante della sharding all'applicazione attraverso mongos, quindi l'applicazione vede l'intero set di dati.
Primo, shard primario
Non ogni collezione viene archiviata distribuitamente nel cluster di shard. Solo quando si shardizza esplicitamente la collezione utilizzando sh.shardCollection(), la collezione viene archiviata distribuitamente su diversi shard. Per le collezioni non shard (un-sharded collection), i dati vengono archiviati solo nel shard primario (Primary shard). Per impostazione predefinita, lo shard primario è lo shard originale utilizzato per archiviare le collezioni non shard del database. Ogni database ha il proprio shard primario.
Ogni database in un cluster di shard ha uno shard primario che contiene tutte le collezioni non shard di quel database. Ogni database ha il proprio shard primario.
Ad esempio, un cluster di shard con tre shard: shard1, shard2, shard3. Se si crea un database blog nel shard shard1, se si shardizza il database blog, MongoDB creerà automaticamente un database blog con la stessa struttura nei shard shard2 e shard3, e lo shard primario del database blog è Shard1.
Illustrazione: lo shard primario della Collection2 è ShardA.
Utilizzare il comando movePrimary per modificare lo shard primario predefinito del database. Le collezioni non shard verranno spostate dallo shard corrente al nuovo shard primario.
db.runCommand( { movePrimary : "test", to : "shard0001" } )
Dopo aver modificato il shard primario del database con il comando movePrimary, le informazioni di configurazione nel server di configurazione sono aggiornate, mentre le informazioni di configurazione nella cache di mongos sono diventate obsolete.MongoDB fornisce il comando: flushRouterConfig per forzare mongos a ottenere le informazioni di configurazione più recenti dal server di configurazione, aggiornando la cache di mongos.
db.adminCommand({"flushRouterConfig":1})
Secondo, metadata del shard
Non direttamente sul server di configurazione per visualizzare le informazioni metadata del cluster di shard, questi dati sono molto importanti. Il modo sicuro è connettersi al database di configurazione tramite mongos o utilizzare la funzione assistente sh.
Usa la funzione assistente sh per visualizzare
sh.status()
Connettiti a mongos per visualizzare le collection del database config
mongos> use config
1, l'insieme shards保存分片信息
db.shards.find()
I dati dello shard sono memorizzati nel replica set o nel mongod standalone specificato da host.
{ "_id" : "shard_name", "host" : "replica_set_name/host:port", "tag":[shard_tag1,shard_tag2]
2, l'insieme databases保存分片集群中所有数据库的信息,不管数据库是否分片
db.databases.find()
Se si esegue sh.enableSharding(“db_name”) sul database, il valore del campo partitioned è true; il campo primary specifica lo shard principale (primary shard) del database.
{ "_id" : "test", "primary" : "rs0", "partitioned" : true
3, l'insieme collections保存所有已分片集合的信息,不包括非分片集合(un-sharded collections)
key è: la chiave di segmentazione del segmento
db.collections.find() { "_id" : "test.foo", "lastmodEpoch" : ObjectId("57dcd4899bd7f7111ec15f16"), "lastmod" : ISODate("1970-02-19T17:02:47.296Z"), "dropped" : false, "key" : { "_id" : 1 }, "unique" : true
4, l'insieme chunks保存数据块信息,
ns:insieme di segmentazione, struttura: db_name.collection_name
min e max: valore minimo e massimo della chiave di segmentazione
shard:块所在的分片
db.chunks.find() { "_id" : "test.foo-_id_MinKey", "lastmod" : Timestamp(1, 1), "lastmodEpoch" : ObjectId("57dcd4899bd7f7111ec15f16"), "ns" : "test.foo", "min" : {}} "_id" : 1 }, "max" : { "_id" : 3087 }, "shard" : "rs0"
5, La raccolta di changelog registra le operazioni del cluster di shard, inclusi le operazioni di divisione e migrazione dei chunk, l'aggiunta o la rimozione di shard
Il campo what: indica il tipo di operazione, ad esempio: multi-split indica la divisione dei chunk,
"what" : "addShard", "what" : "shardCollection.start", "what" : "shardCollection.end", "what" : "multi-split",
6, Le tags registrano il tag del shard e la gamma di chiavi delle partizioni corrispondenti
{ "_id" : { "ns" : "records.users", "min" : { "zipcode" : "10001" } }, "ns" : "records.users", "min" : { "zipcode" : "10001" }, "max" : { "zipcode" : "10281" }, "tag" : "NYC"
7, La raccolta di settings registra lo stato del bilanciatore e la dimensione dei chunk, la dimensione predefinita dei chunk è di 64MB.
{"_id" : "chunksize", "value" : 64 } {"_id" : "balancer", "stopped" : false }
8, La raccolta di locks registra il lock distribuito (distributed lock), garantendo che solo una istanza di mongos possa eseguire task amministrativi nel cluster di shard.
Quando il mongos agisce come bilanciatore, ottiene un lock distribuito e inserisce un documento in config.locks.
La raccolta di chiavi memorizza un lock distribuito. Questo garantisce che solo una istanza di mongos possa eseguire task amministrativi sul cluster in una volta. Il mongos che agisce come bilanciatore acquisisce un lock inserendo un documento simile al seguente nella raccolta di chiavi.
{ "_id": "balancer" "process": "example.net:40000:1350402818:16807", "state": 2, "ts": ObjectId("507daeedf40e1879df62e5f3"), "when": ISODate("2012-10-16T19:01:01.593Z"), "who": "example.net:40000:1350402818:16807:Balancer:282475249", "why": "doing balance round"
Terzo, eliminare il segmento
Eliminando il segmento, è necessario assicurarsi che i dati del segmento siano stati spostati su altri segmenti, per le raccolte segmentate, utilizzare il bilanciatore per trasferire i segmenti, per le raccolte non segmentate, è necessario modificare il segmento principale della raccolta.
1, eliminare i dati della raccolta segmentata esistente
step1, assicurarsi che il bilanciatore sia attivato
sh.setBalancerState(true);
step2, trasferire l'intera raccolta segmentata a un altro segmento
use admin db.adminCommand({"removeShard":"shard_name"})
il comando removeShard trasferisce i segmenti da un segmento corrente a un altro segmento, se ci sono molti segmenti nel segmento, il processo di trasferimento potrebbe richiedere molto tempo.
step3, controllare lo stato del trasferimento dei dati dei segmenti
use admin db.runCommand({ removeShard: "shard_name" })
l'uso del comando removeShard permette di visualizzare lo stato del trasferimento dei dati dei segmenti, il campo remaining indica il numero di segmenti rimanenti
{ "msg": "draining ongoing", "state": "ongoing", "remaining": { "chunks": 42, "dbs": 1 }, "ok" : 1
step4, il trasferimento dei dati dei segmenti è completato
use admin db.runCommand({ removeShard: "shard_name" }) { "msg": "removeshard completed successfully", "state": "completed", "shard" : "shard_name", "ok" : 1
2, elimina i database non sharded
Passaggio 1, visualizza i database non sharded
I database non sharded includono due parti:
1, il database non è sharded, i dati non utilizzano sh.enableSharding(“db_name”) , nel database config, il campo partitioned di questo database è false
2, esiste una collection non sharded nel database, ossia lo shard corrente è lo shard principale di questa collection
use config db.databases.find({$or:[{"partitioned":false},{"primary":"shard_name"}]})
Per i database con partitioned=false, tutti i dati sono conservati nello shard corrente; per i database con partitioned=true e primary="shard_name", significa che ci sono collection non sharded (un-sharded collection) memorizzate in questo database, è necessario modificare lo shard principale di queste collection.
Passaggio 2, modifica lo shard principale del database
db.runCommand( { movePrimary: "db_name", to: "new_shard" })
Quattro, aggiungere sharding
Poiché lo sharding archivia solo una parte del dataset, per garantire l'alta disponibilità dei dati, si raccomanda di utilizzare un Replica Set come shard, anche se il Replica Set contiene solo un membro. Connettiti a mongos e utilizza la funzione assistente sh per aggiungere lo sharding.
sh.addShard("replica_set_name/host:port")
Non si raccomanda di utilizzare mongod standalone come shard
sh.addShard("host:port")
Cinque, chunk gigante
In alcuni casi, il chunk può continuare a crescere, superando i limiti di dimensione del chunk e diventando un chunk gigante (jumbo chunk). La ragione per cui si verifica un chunk gigante è che tutti i doc nel chunk utilizzano la stessa chiave di shard (shard key), il che rende impossibile dividere il chunk di MongoDB. Se questo chunk continua a crescere, può causare una distribuzione iniqua del chunk, diventando un collo di bottiglia per le prestazioni.
Nel trasferimento di chunk, ci sono limitazioni: la dimensione massima di ogni chunk non può superare 25.000 doc, o 1.3 volte il valore di configurazione. Il valore di configurazione predefinito per la dimensione del chunk è 64MB, i chunk che superano i limiti vengono etichettati come chunk gigante (jumbo chunk) da MongoDB, che non può trasferire i chunk giganti su altri shard.
MongoDB non può muovere un blocco se il numero di documenti nel blocco supera 250000 documenti o 1,3 volte il risultato della divisione della dimensione del blocco configurata per la dimensione media del documento.
1, visualizzare i grandi blocchi
Utilizzando sh.status(), è possibile trovare i grandi blocchi, dietro i grandi blocchi esiste il segno jumbo
{ "x" : 2 } -->> { "x" : 3 } on : shard-a Timestamp(2, 2) jumbo
2, distribuire i grandi blocchi
I grandi blocchi non possono essere suddivisi, non possono essere distribuiti automaticamente tramite il bilanciatore, devono essere distribuiti manualmente.
step1, chiudere il bilanciatore
sh.setBalancerState(false)
step2, aumentare il valore di configurazione della dimensione del chunk
Poiché MongoDB non consente di spostare grandi blocchi di dimensioni superiori al limite, è necessario aumentare temporaneamente il valore di configurazione della dimensione del blocco e poi distribuire uniformemente i grandi blocchi nel cluster di shard.
use config db.settings.save({"_id":"chunksize","value":"1024"})
step3, spostare il grande blocco
sh.moveChunk("db_name.collection_name",{sharded_filed:"value_in_chunk"},"new_shard_name")
step4, abilitare il bilanciatore
sh.setBalancerState(true)
step5, aggiornare la cache di configurazione di mongos
Forza mongos a sincronizzare le informazioni di configurazione dal server di configurazione e a aggiornare la cache.
use admin db.adminCommand({ flushRouterConfig: 1 })
Sei, bilanciatore
Il bilanciatore è trasformato da mongos, il che significa che mongos non solo è responsabile di inoltrare le query al shard appropriato, ma anche di equilibrare i blocchi di dati. Di solito, MongoDB gestisce automaticamente l'equilibrio dei dati, illo stato del bilanciatore può essere visualizzato tramite config.settings o tramite le funzioni di assistenza sh
sh.getBalancerState()
Ritorna true, indica che il bilanciatore è in esecuzione, il sistema gestisce automaticamente l'equilibrio dei dati, l'uso della funzione di assistenza sh può chiudere il bilanciatore
sh.setBalancerState(false)
Il balancer non può interrompere immediatamente l'operazione di migrazione dei chunk in corso, quando il mongos diventa balancer, richiede un lock di balancer, controlla il set di collection config.locks.
use config db.locks.find({"_id":"balancer"}) --or sh.isBalancerRunning()
Se state=2, significa che il balancer è in stato attivo, se state=0, significa che il balancer è stato chiuso.
Il processo di equalizzazione consiste nel trasferire i dati dai shard a altri shard, o prima di dividere un chunk grande in chunk più piccoli, poi迁移这些小块到其他shard上,块的迁移和拆分都会增加系统的IO负载,最好在系统空闲时进行均衡器的活跃时间限制,可以设置balancer的活跃时间窗口,限制balancer在指定的时间区间内进行数据块的拆分和迁移操作。
use config db.settings.update( {"_id":"balancer"}, {"$set":{"activeWindow":{"start":"23:00","stop":"04:00"}}}), true )
Gli oggetti spostati e divisi dall'equalizzatore sono i chunk, l'equalizzatore garantisce solo che il numero di chunk sia equamente distribuito su ciascun shard, mentre il numero di doc contenuti in ciascun chunk non è necessariamente equo. Potrebbe esserci alcuni chunk che contengono un gran numero di doc, mentre altri contengono pochi doc, o addirittura nessun doc. Pertanto, è necessario scegliere attentamente la chiave di indexazione dello shard, ossia lo shard key, se un campo può soddisfare la maggior parte delle esigenze di query e distribuire uniformemente il numero di doc, allora tale campo è la migliore scelta per lo shard key.
Conclusione
Questo è tutto il contenuto dell'articolo, spero che possa essere di aiuto per il vostro studio o lavoro. Se avete domande, potete lasciare un commento per discuterle.