Sharding es un proceso de división de la gran escala de conjuntos de datos en un trozo de conjuntos de datos más pequeños a través de múltiples instancias MongoDB en un entorno distribuido.
¿Qué es el sharding?
Fragmentación de MongoDB nos proporciona una solución escalable para almacenar una gran cantidad de datos entre el número de servidores en lugar de almacenarlos en un único servidor.
En términos prácticos, no es factible almacenar datos que crecen exponencialmente en una sola máquina. La consulta de una enorme cantidad de datos almacenados en un único servidor podría dar lugar a una elevada utilización de recursos y podría no proporcionar un rendimiento satisfactorio de lectura y escritura.
Básicamente, existen dos tipos de métodos de escalado para acomodar el crecimiento de los datos con el sistema:
- Vertical
- Horizontal
El escaladovertical consiste en mejorar el rendimiento de un único servidor añadiendo procesadores más potentes, mejorando la memoria RAM o añadiendo más espacio de disco al sistema. Pero existen las posibles implicaciones de aplicar el escalado vertical en casos de uso práctico con la tecnología y las configuraciones de hardware existentes.
El escaladohorizontal consiste en añadir más servidores y distribuir la carga en varios servidores. Dado que cada máquina manejará el subconjunto de todo el conjunto de datos, proporciona una mayor eficiencia y una solución más rentable que desplegar el hardware de gama alta. Pero requiere un mantenimiento adicional de una infraestructura compleja con un gran número de servidores.
Mongo DB sharding funciona con la técnica de escalado horizontal.
Componentes de fragmentación
Para lograr el sharding en MongoDB, se requieren los siguientes componentes:
Fragmento es una instancia de Mongo para manejar un subconjunto de datos originales. Se requiere que los fragmentos se desplieguen en el conjunto de réplicas.
Mongos es una instancia de Mongo y actúa como interfaz entre una aplicación cliente y un clúster sharded. Funciona como un enrutador de consultas a los shards.
Configurar El servidor es una instancia Mongo que almacena información de metadatos y detalles de configuración del clúster. MongoDB requiere que el servidor de configuración se despliegue como un conjunto de réplicas.
Arquitectura de fragmentación
El clúster MongoDB consiste en un número de conjuntos de réplica.
Cada conjunto de réplica consta de un mínimo de 3 o más instancias mongo. Un cluster sharded puede consistir en múltiples instancias mongo shards, y cada instancia shard trabaja dentro de un conjunto de réplica shard. La aplicación interactúa con mongo , que a su vez se comunica con los fragmentos. Por lo tanto, en Sharding, las aplicaciones nunca interactúan directamente con los nodos shard. El enrutador de consultas distribuye los subconjuntos de datos entre los nodos shards basándose en la clave shard.

Implementación de la fragmentación
Siga los siguientes pasos para la fragmentación
Paso 1
- Inicie el servidor de configuración en el conjunto de réplicas y habilite la replicación entre ellas.
mongod --configsvr --port 27019 --replSet rs0 --dbpath C:\data\data1 --bind_ip localhost
mongod --configsvr --port 27018 --replSet rs0 --dbpath C:\data\data2 --bind_ip localhost
mongod --configsvr --port 27017 --replSet rs0 --dbpath C:\data\data3 --bind_ip localhost
Paso 2
- Inicialice el conjunto de réplica en uno de los servidores de configuración.
rs.initiate( { _id : "rs0", configsvr: true, members: [ { _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, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1593569257, 1)
}
Paso 3
- Inicie los servidores sharding en el conjunto de réplicas y habilite la réplica entre ellos.
mongod --shardsvr --port 27020 --replSet rs1 --dbpath C:\data\data4 --bind_ip localhost
mongod --shardsvr --port 27021 --replSet rs1 --dbpath C:\data\data5 --bind_ip localhost
mongod --shardsvr --port 27022 --replSet rs1 --dbpath C:\data\data6 --bind_ip localhost
MongoDB inicializa el primer servidor de fragmentación como Primario, para mover el servidor de fragmentación primario utilice el método movePrimary.
Paso 4
- Inicialice el conjunto de réplicas en uno de los servidores de fragmentación.
rs.initiate( { _id : "rs0", members: [ { _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)
}
Paso 5
- Inicie los mangos para el cluster sharded
mongos --port 40000 --configdb rs0/localhost:27019,localhost:27018, localhost:27017
Paso 6
- Conecte el servidor de rutas mongo
mongo --port 40000
- Ahora, añada servidores sharding.
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, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
Paso 7
- En mongo shell habilite la fragmentación en la BD y las colecciones.
- Habilitar la fragmentación en la BD
sh.enableSharding("geekFlareDB")
sh.enableSharding("geekFlareDB")
{
"ok" : 1,
"operationTime" : Timestamp(1591630612, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1591630612, 1),
"signature" : {
"hash" : BinData(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
Paso 8
- Para fragmentar la colección se necesita la clave shard (descrita más adelante en este artículo).
Sintaxis: sh.shardCollection("dbName.collectionName", { "key" : 1 } )<br>
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, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
Nota si la colección no existe, créela de la siguiente manera.
db.createCollection("geekFlareCollection")
{
"ok" : 1,
"operationTime" : Timestamp(1593570344, 4),
"$clusterTime" : {
"clusterTime" : Timestamp(1593570344, 5),
"signature" : {
"hash" : BinData(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
Paso 9
Inserte los datos en la colección. Los registros de Mongo comenzarán a crecer, e indicarán que un balanceador está en acción e intentando equilibrar los datos entre los shards.
Paso 10
El último paso es comprobar el estado del sharding. El estado puede comprobarse ejecutando el siguiente comando en el nodo de ruta de Mongos.
Estado de la fragmentación
Compruebe el estado de la fragmentación ejecutando el siguiente comando en el nodo de ruta mongo.
sh.status()
mongos> sh.status()
--- Estado de la fragmentación ---
versión de la fragmentación: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("5ede66c22c3262378c706d21")
}
shards:
{ "_id" : "rs1", "host" : "rs1/localhost:27020,localhost:27021,localhost:27022", "state" : 1 }
mongos activos:
"4.2.7" : 1
autosplit:
Actualmente habilitado: sí
balancer:
Actualmente habilitado: sí
Actualmente en ejecución: no
Rondas del equilibrador fallidas en los últimos 5 intentos: 5
Último error notificado: No se ha podido encontrar el host que coincida con la preferencia de lectura { mode: "primary" } para el conjunto rs1
Hora del error notificado: Tue Jun 09 2020 15:25:03 GMT 0530 (India Standard Time)
Resultados de la migración de las últimas 24 horas:
No hay migraciones recientes
bases de datos:
{ "_id" : "config", "primary" : "config", "partitioned" : true }
config.system.sessions
shard key: { "_id" : 1 }
unique: false
balancing: true
chunks:
rs1 1024
demasiados chunks para imprimir, use verbose si quiere forzar la impresión
{ "_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 } } -->
> { "producto" : { "$maxClave" : 1 } } on : rs1 Timestamp(1, 0)
{ "_id" : "test", "primary" : "rs1", "partitioned" : false, "version" : { "uuid" : UUID("fbc00f03-b5b5-4d13-9d09-259d7fdb7289"), "lastMod" : 1 } }
mongos>
Distribución de datos
El enrutador Mongos distribuye la carga entre los fragmentos basándose en la clave del fragmento, y para distribuir uniformemente los datos, entra en acción el equilibrador.
Los componentes clave para distribuir los datos entre los shards son
- Un El equilibrador desempeña el papel de equilibrar el subconjunto de datos entre los nodos sharded. El equilibrador se ejecuta cuando el servidor Mongos comienza a distribuir las cargas entre los shards. Una vez iniciado, el equilibrador distribuye los datos de forma más uniforme. Para comprobar el estado del equilibrador ejecute sh
<strong>.status()</strong>
osh.getBalancerState()
osh<code class="language-markup">.isBalancerRunning()
.
mongos> sh.isBalancerRunning()
true
mongos>
O
mongos> sh.getBalancerState()
true
mongos>
Tras insertar los datos, podríamos notar cierta actividad en el demonio de Mongos indicando que está moviendo algunos chunks para los shards específicos y demás, es decir, el balanceador estará en acción intentando equilibrar los datos entre los shards. La ejecución del equilibrador podría provocar problemas de rendimiento, por lo que se sugiere ejecutarlo dentro de una ventana del equilibrador determinada.
mongos> sh.status()
--- Estado del sharding ---
versión del sharding: {
"_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 }
mongos activos:
"4.2.7" : 1
autosplit:
Actualmente habilitado: sí
balancer:
Actualmente habilitado: sí
Actualmente en ejecución: sí
Rondas del equilibrador fallidas en los últimos 5 intentos: 5
Último error notificado: No se ha podido encontrar el host que coincida con la preferencia de lectura { mode: "primary" } para el conjunto rs2
Hora del error notificado: Wed Jul 01 2020 14:39:59 GMT 0530 (India Standard Time)
Resultados de la migración de las últimas 24 horas:
1024 : Éxito
bases de datos:
{ "_id" : "config", "primary" : "config", "partitioned" : true }
config.system.sessions
shard key: { "_id" : 1 }
unique: false
balancing: true
chunks:
rs2 1024
demasiados chunks para imprimir, use verbose si quiere forzar la impresión
{ "_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>
- Fragmento La clave determina la lógica para distribuir los documentos de la colección sharded entre los shards. La clave del shard puede ser un campo indexado o un campo compuesto indexado que debe estar presente en todos los documentos de la colección que se vaya a insertar. Los datos se particionarán en trozos, y cada trozo se asociará a la clave shard basada en el rango. En función de la consulta de rango, el enrutador decidirá qué shard almacenará el chunk.
La clave defragmento puede seleccionarse teniendo en cuenta cinco propiedades :
- Cardinalidad
- Distribución de la escritura
- Distribución de lectura
- Orientación de lectura
- Localidad de lectura
Una clave de shard ideal hace que MongoDB distribuya uniformemente la carga entre todos los shard. Elegir una buena clave de shard es extremadamente importante.

Eliminación del nodo shard
Antes de eliminar los shards del clúster, el usuario debe garantizar la migración segura de los datos a los shards restantes. MongoDB se encarga de drenar de forma segura los datos a otros nodos shards antes de la eliminación del nodo shard requerido.
Ejecute el siguiente comando para eliminar el fragmento requerido.
Paso 1
En primer lugar, necesitamos determinar el nombre de host del shard a eliminar. El siguiente comando listará todos los shards presentes en el cluster junto con el estado del shard.
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)
}
}
}
Paso 2
Emita el siguiente comando para eliminar el fragmento necesario del clúster. Una vez emitido, el equilibrador se encarga de la eliminación de los chunks del nodo shard que se está vaciando y, a continuación, equilibra la distribución de los chunks restantes entre el resto de nodos shards.
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" : "drenaje iniciado con éxito",
"state" : "iniciado",
"shard" : "rs1",
"note" : "necesita eliminar o moverPrimary estas bases de datos",
"dbsToMove" : [ ],
"ok" : 1,
"operationTime" : Timestamp(1593572385, 2),
"$clusterTime" : {
"clusterTime" : Timestamp(1593572385, 2),
"signature" : {
"hash" : BinData(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
Paso 3
Para comprobar el estado del fragmento de vaciado, vuelva a emitir el mismo comando.
db.adminCommand( { removeShard: "rs1/127.0.0.1:27020,127.0.0.1:27021,127.0.0.1:27022" } )
Los campos “ msg" y " estado " mostrarán si el vaciado de los datos se ha completado o no, como sigue
"msg" : "vaciado en curso",
"estado" : "en curso",
También podemos comprobar el estado con el comando sh.status()
. Una vez eliminado el nodo sharded no se reflejará en la salida. Pero si el drenaje está en curso, el nodo sharded vendrá con el estado de drenaje como verdadero.
Paso 4
Siga comprobando el estado de drenaje con el mismo comando anterior, hasta que el fragmento requerido sea eliminado por completo.
Una vez completado, la salida del comando reflejará el mensaje y el estado como completado.
"msg" : "removeshard completed successfully",
"state" : "completed",
"shard" : "rs1",
"ok" : 1,
Paso 5
Finalmente, necesitamos comprobar los fragmentos restantes en el cluster. Para comprobar el estado introduzca <strong>sh.status()</strong> o
db <strong>.adminCommand( { listShards: 1 } )</strong>
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)
}
}
}
Aquí podemos ver que el shard eliminado ya no está presente en la lista de shards.
Ventajas de la fragmentación sobre la replicación
- En la replicación, el nodo primario se encarga de todas las operaciones de escritura, mientras que los servidores secundarios deben mantener copias de seguridad o servir operaciones de sólo lectura. Pero en la fragmentación junto con los conjuntos de réplica, la carga se distribuye entre varios servidores.
- Un único conjunto de réplica está limitado a 12 nodos, pero no hay restricciones en el número de fragmentos.
- La replicación requiere hardware de gama alta o escalado vertical para manejar grandes conjuntos de datos, lo que resulta demasiado caro en comparación con la adición de servidores adicionales en la fragmentación.
- En la replicación, el rendimiento de lectura puede mejorarse añadiendo más servidores esclavos/secundarios, mientras que, en la fragmentación, tanto el rendimiento de lectura como el de escritura mejorarán añadiendo más nodos de fragmentación.
Limitación de la fragmentación
- El cluster sharded no soporta la indexación única a través de los shards hasta que el índice único es prefijado con la clave completa del shard.
- Todas las operaciones de actualización de una colección fragmentada, ya sea sobre uno o varios documentos, deben contener la clave fragmentada o el campo _id en la consulta.
- Las colecciones pueden ser fragmentadas si su tamaño no supera el umbral especificado. Este umbral puede estimarse en función del tamaño medio de todas las claves de fragmentación y del tamaño configurado de los fragmentos.
- La fragmentación comprende límites operativos sobre el tamaño máximo de la colección o el número de divisiones.
- La elección de claves de fragmentación erróneas puede repercutir en el rendimiento.
Conclusión
MongoDB ofrece sharding incorporado para implementar una gran base de datos sin comprometer el rendimiento. Espero que lo anterior le ayude a configurar el sharding de MongoDB. A continuación, puede que desee familiarizarse con algunos de los comandos de MongoDB más utilizados.