English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Comprender profundamente la gestión de fragmentación en MongoDB

Prólogo

En MongoDB (versión 3.2.9En el clúster de fragmentación (sharded cluster), es un método de expansión horizontal del rendimiento de la base de datos, que puede almacenar el conjunto de datos distribuidamente en diferentes shards (shard), cada shard solo almacena una parte del conjunto de datos. MongoDB garantiza que no haya datos repetidos entre los diferentes shards, y la suma de los datos almacenados en todos los shards es el conjunto de datos completo. El clúster de fragmentación almacena el conjunto de datos distribuidamente, lo que permite distribuir la carga en varios shards, cada shard solo es responsable de leer y escribir una parte de los datos, aprovechando al máximo los recursos del sistema de cada shard y aumentando la capacidad de procesamiento de la base de datos.

El conjunto de datos se divide en bloques de datos (chunk), cada bloque contiene varios documentos (doc), y los bloques se almacenan de manera distribuida en el clúster de fragmentación. MongoDB es responsable de rastrear la información de distribución de los bloques de datos en los shards, cada shard almacena qué bloques de datos, denominados metadatos del shard, y se almacenan en la base de datos config en el servidor de configuración, generalmente se usa3Hay un servidor de configuración, todos los bancos de datos de configuración en los servidores de configuración deben ser completamente idénticos. A través de mongos, se puede acceder directamente a la base de datos de configuración y ver los metadatos de los shards; el shell de mongo proporciona la función auxiliar sh, que permite ver de manera segura la información de metadatos del clúster de fragmentación.

Para realizar una consulta en cualquier shard, solo se obtiene el subconjunto de datos de la colección en el shard actual, no todo el conjunto de datos. La aplicación solo necesita conectarse a mongos y realizar operaciones de lectura y escritura, mongos enruta automáticamente las solicitudes de lectura y escritura a los shards correspondientes. MongoDB oculta la implementación subyacente de la fragmentación a la aplicación a través de mongos, por lo que la aplicación ve que accede a todo el conjunto de datos.

Primero, el shard primario

En un clúster fragmentado, no todas las colecciones se almacenan de manera distribuida, solo las colecciones que se hayan fragmentado explícitamente utilizando sh.shardCollection() se almacenarán distribuidamente en diferentes shards. Para las colecciones no fragmentadas (un-colección sin fragmentar),sus datos se almacenarán solo en el shard primario (Primary shard), por defecto, el shard primario es el shard que se creó originalmente para la base de datos, utilizado para almacenar los datos de las colecciones no fragmentadas de la base de datos. Cada base de datos tiene su propio shard primario.

Cada base de datos en un clúster fragmentado tiene un shard primario que contiene todos los datos de la colección sin fragmentar-colecciones fragmentadas para esa base de datos. Cada base de datos tiene su propio shard primario.

Por ejemplo, un clúster de fragmentación con tres fragmentos: shard1, shard2, shard3, en el shard fragmentado1Crear una base de datos blog. Si se fragmenta la base de datos bolg, MongoDB creará automáticamente en el shard2, shard3Crear una base de datos blog con la misma estructura en la que, la Shard primaria de la base de datos blog es Shard1.

En la ilustración, Colección2El shard primario es ShardA.

Utilizar el comando movePrimary para cambiar el shard primario predeterminado de la base de datos, las colecciones no fragmentadas se moverán del shard actual al shard primario nuevo.

db.runCommand({ movePrimary : "test", to : "shard0001})

Después de cambiar el shard primario de la base de datos utilizando el comando movePrimary, la información de configuración en el servidor de configuración es la más reciente, mientras que la información de configuración en la caché de mongos se vuelve obsoleta.MongoDB proporciona el comando: flushRouterConfig que fuerza a mongos a obtener la información de configuración más reciente del servidor de configuración, actualizando la caché de mongos.

db.adminCommand({"flushRouterConfig":}1})

Dos, metadatos de shard

No acceda directamente a los servidores de configuración para ver la información de metadatos del clúster de shard, estos datos son muy importantes. La manera segura es conectarse a la base de datos config a través de mongos o utilizar la función auxiliar sh

Verifique utilizando la función auxiliar sh

sh.status()

Conéctese a mongos para ver las colecciones en la base de datos config

mongos> use config

1,la colección shards almacena información sobre las secciones

db.shards.find()

Los datos del shard se almacenan en el replica set o mongod standalone especificado por el host.

{
 "_id" : "shard_name",
 "host" : "replica_set_name"/host:puerto",
 "tag":[shard_tag1,shard_tag2] 
}

2,la colección databases almacena información sobre todas las bases de datos en el clúster de shard, independientemente de si las bases de datos están shardeadas o no

db.databases.find()

Si se ejecuta sh.enableSharding(“db_name”) en la base de datos, el valor del campo partitioned es true; el campo primary especifica el shard primario (primary shard) de la base de datos.

{
 "_id" : "test",
 "primary" : "rs0",
 "partitioned" : true
}

3,la colección collections almacena información sobre todas las colecciones shardeadas, no incluye colecciones no shardeadas (un-colecciones shardeadas)

la clave es: la clave de la sección de la sección

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,la colección chunks almacena información sobre los bloques de datos,

ns:conjunto de secciones, estructura: db_name.collection_name

min y max: valor mínimo y máximo de la clave de la sección

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

5La colección de changelog registra las operaciones del clúster de fragmentación, incluyendo la división y migración de fragmentos, la adición o eliminación de fragmentos,

El campo what: representa el tipo de operación, por ejemplo: multi-La división representa la división del fragmento,

"what" : "addShard"
"what" : "shardCollection.start"
"what" : "shardCollection.end" 
"what" : "multi"-,

6La colección de etiquetas registra la etiqueta del fragmento y el rango de la clave del fragmento correspondiente

{
 "_id" : { "ns" : "records.users", "min" : { "zipcode" : "10001}
 "ns" : "records.users",
 "min" : { "zipcode" : "10001}
 "max" : { "zipcode" : "10281}
 "tag" : "NYC"
}

7La colección de configuraciones registra el estado del balanceador y el tamaño de los fragmentos, el tamaño de fragmento predeterminado es64MB.

{"_id" : "chunksize", "value" :} 64 }
{"_id" : "balancer", "stopped" : false }

8La colección de cerraduras registra el cierre distribuido (cierre distribuido), asegurando que solo una instancia de mongos pueda ejecutar tareas administrativas en el clúster de fragmentación.

Cuando mongos actúa como balanceador, obtiene un cierre distribuido e inserta un documento en config.locks.

La colección de cerraduras almacena un cierre distribuido. Esto asegura que solo una instancia de mongos pueda realizar tareas administrativas en el clúster al mismo tiempo. El mongos que actúa como balanceador toma un cierre insertando un documento similar al siguiente en la colección de cerraduras.

{
 "_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": "realizando ronda de balance"
}

Tercero, eliminar el shard

Al eliminar un shard, debe asegurarse de que los datos del shard se hayan movido a otros shards, para las colecciones fragmentadas, usar el balanceador para transferir los datos de los shards, para las colecciones no fragmentadas, debe modificar el shard principal de la colección.

1,eliminar los datos de la colección fragmentada

step1,asegurar que el均衡器 está activado

sh.setBalancerState(true);

step2,mover la colección fragmentada a otros shards

use admin
db.adminCommand({"removeShard":"shard_name"})

El comando removeShard mueve los datos de un shard a otro shard, si hay muchos datos en el shard, el proceso de transferencia puede llevar mucho tiempo.

step3,verificar el estado de la transferencia de datos

use admin
db.runCommand({ removeShard: "shard_name" })

El comando removeShard permite ver el estado de la transferencia de datos, el campo remaining indica la cantidad de datos restantes

{
  "msg": "draining ongoing",
 "state": "ongoing",
 "remaining": {
  "chunks": 42,
  "dbs": 1
 },
 "ok" : 1
}

step4,los datos se han transferido con éxito

use admin
db.runCommand({ removeShard: "shard_name" })
{
 "msg": "removeshard completed successfully",
 "state": "completed",
 "shard" : "shard_name"
 "ok" : 1
}

2Eliminar las bases de datos no shardeadas

step1Ver las bases de datos no shardeadas

Las bases de datos no shardeadas incluyen dos partes:

     1La base de datos no está shardeada, este conjunto de datos no utiliza sh.enableSharding(“db_name”) , en la base de datos config, el campo partitioned de esta base de datos es false

     2La base de datos contiene colecciones no shardeadas, es decir, el shard actual es el shard principal de esta colección

use config
db.databases.find({$or:[{"partitioned":false},{"primary":"shard_name"}]})

Para las bases de datos con partitioned=false, todos los datos se almacenan en el shard actual; para las bases de datos con partitioned=true y primary="shard_name", indica que hay bases de datos no shardeadas (un-Las colecciones sharded que se almacenan en esta base de datos deben cambiar el shard principal de estas colecciones.

step2Modificar el shard principal de la base de datos

db.runCommand( { movePrimary: "db_name", to: "new_shard" })

Cuatro, agregar sharding

Dado que el sharding almacena una parte de la colección de datos, para garantizar la alta disponibilidad de los datos, se recomienda utilizar un Replica Set como shard, incluso si el Replica Set solo contiene un miembro. Conéctese a mongos y utilice la función auxiliar sh para agregar sharding.

sh.addShard("replica_set_name/host:port)

No se recomienda utilizar mongod standalone como shard

sh.addShard("host:port")

Cinco, chunks jumbo

En algunos casos, el chunk puede crecer continuamente, excediendo el límite del tamaño del chunk y convirtiéndose en un chunk jumbo, la razón de la existencia de chunks jumbo es que todos los documentos del chunk utilizan la misma clave de shard, lo que hace que MongoDB no pueda dividir este chunk. Si este chunk sigue creciendo, puede causar una distribución inhomogénea del chunk, convirtiéndose en un cuello de botella de rendimiento.

Al migrar el chunk, hay limitaciones: el tamaño de cada chunk no puede superar2.510,000 documentos, o1.3Multiplicado por el valor de configuración. El valor predeterminado de configuración para el tamaño del chunk es64MB, los chunks que exceden los límites serán marcados como chunks jumbo por MongoDB, y MongoDB no puede migrar estos chunks a otros shards.

MongoDB no puede mover un bloque si el número de documentos en el bloque excede o supera 250000 documentos o 1.3 multiplicado por el resultado de dividir el tamaño del bloque configurado por el tamaño promedio del documento.

1Ver los bloques grandes

Usar sh.status() para encontrar bloques grandes, el bloque grande tiene el marcador jumbo

 { "x" : 2 } -->> { "x" : 3 }) en: shard-Un Timestamp(2, 2) jumbo

2Distribuir el bloque grande

Los bloques grandes no se pueden dividir, no se pueden distribuir automáticamente a través del balancer, deben distribuirse manualmente.

step1Desactivar el balancer

sh.setBalancerState(false)}

step2Aumentar el valor de configuración del tamaño del bloque

Dado que MongoDB no permite mover bloques grandes que excedan los límites, debe aumentar temporalmente el valor de configuración del tamaño del bloque, y luego distribuir equitativamente el bloque grande en el clúster de shards.

use config
db.settings.save({"_id":"chunksize","value":"1024"})

step3Mover el gran bloque

sh.moveChunk("db_name.collection_name",{sharded_filed:"value_in_chunk"},"new_shard_name")

step4Activar el balancer

sh.setBalancerState(true)

step5Actualizar el caché de configuración de mongos

Forzar a mongos a sincronizar la información de configuración del servidor de configuración y actualizar el caché.

use admin
db.adminCommand({ flushRouterConfig: 1 })

Sexto, balancer

El balancer se transforma por mongos, es decir, mongos no solo es responsable de enrutar consultas a los shards correspondientes, sino también de equilibrar los bloques de datos. En general, MongoDB maneja automáticamente la equidad de datos, se puede ver el estado del balancer a través de config.settings o a través de la función auxiliar sh

sh.getBalancerState()

Devuelve true, lo que indica que el balancer está en ejecución, el sistema maneja automáticamente la equidad de datos, el uso de la función auxiliar sh puede cerrar el balancer

sh.setBalancerState(false)}

El balancer no puede detener inmediatamente la operación de migración de bloques en ejecución, cuando mongos se convierte en balancer, solicita un lock de balancer, consulta el conjunto config.locks,

use config
db.locks.find({"_id":"balancer"})
--o 
sh.isBalancerRunning()

si state=2، lo que significa que el balancer está en estado activo, si state=0, significa que el balancer ha sido cerrado.

El proceso de equilibrio es en realidad mover los bloques de datos de un shard a otro shard, o primero dividir un gran chunk en pequeños chunks y luego mover los pequeños chunks a otros shards, la migración y división de bloques aumentan la carga IO del sistema, es mejor limitar el tiempo activo del equilibrador durante el tiempo de inactividad del sistema, se puede configurar el tiempo activo de la ventana del balancer para limitar que el balancer realice operaciones de división y migración de bloques en un intervalo de tiempo especificado.

use config
db.settings.update(
  {"_id":"balancer"},
  "$set":{"activeWindow":{"start":"23:00","stop":"04:00"}}),
  true
)

Los objetos que se dividen y mueven el equilibrador son chunk, el equilibrador solo garantiza que la cantidad de chunk sea equilibrada en cada shard, pero no necesariamente la cantidad de doc en cada chunk. Puede haber algunos chunk con una gran cantidad de doc y otros con muy pocos, o incluso sin doc. Por lo tanto, se debe elegir con cautela la clave de índice de shard, es decir, la clave de shard. Si un campo puede satisfacer la mayoría de las necesidades de consulta y distribuir uniformemente la cantidad de doc, ese campo es la mejor opción para la clave de shard.

Resumen

Esto es todo el contenido de este artículo, espero que pueda ayudarles en su aprendizaje o trabajo. Si tienen alguna pregunta, pueden dejar comentarios para discutir.

Te gustará también