====== Implementació de Hash-Based Sharding usant MongoDB i Docker ======
{{tag> CetiMp03 CiberMp03 mongodb docker sharding basesdedades cluster replicaset }}
===== Introducció =====
El ''sharding'' és una tècnica de particionament horitzontal utilitzada per distribuir dades entre múltiples servidors MongoDB.
Permet:
* escalar horitzontalment,
* distribuir càrrega,
* millorar el rendiment,
* augmentar la disponibilitat.
MongoDB implementa ''sharding'' de forma nativa mitjançant clusters distribuïts.
===== Tipus de sharding =====
==== Range-based sharding ====
Les dades es distribueixen per rangs de valors.
Exemple:
* ID 1-1000 → shard1
* ID 1001-2000 → shard2
Aquest sistema pot generar ''hotspots'' si moltes escriptures es concentren en un mateix rang.
==== Hash-based sharding ====
S'aplica una funció hash sobre la ''Shard Key''.
Avantatges:
* distribució uniforme,
* balanceig automàtic,
* evita hotspots.
És l’estratègia recomanada per càrregues generals.
==== List-based sharding ====
Les dades es reparteixen segons valors predefinits.
Exemple:
* Espanya → shard1
* França → shard2
===== Components d’un cluster MongoDB =====
^ Component ^ Funció ^
| Config Server | Emmagatzema les metadades del cluster |
| Shards | Emmagatzemen les dades |
| Mongos | Router que distribueix les peticions |
===== Arquitectura =====
+----------------+
| Mongos |
+--------+-------+
|
+----------------+----------------+
| |
+----+----+ +----+----+
| Shard1 | | Shard2 |
+---------+ +---------+
+------------------+
| Config Server |
+------------------+
===== Exemple pràctic sobre Fedora Linux=====
==== Crear directori de treball ====
mkdir /mongodb-sharding
cd /mongodb-sharding
==== Crear el Docker Compose ====
Crear el fitxer ''docker-compose.yml'':
version: "3.8"
services:
configsvr:
container_name: configsvr
image: mongo:4.4
restart: always
command: >
mongod --configsvr --replSet configReplSet --port 27019 --bind_ip_all
ports:
- "27019:27019"
volumes:
- configdb:/data/db
shard1:
container_name: shard1
image: mongo:4.4
restart: always
command: >
mongod --shardsvr --replSet shard1ReplSet --port 27018 --bind_ip_all
ports:
- "27018:27018"
volumes:
- shard1db:/data/db
shard2:
container_name: shard2
image: mongo:4.4
restart: always
command: >
mongod --shardsvr --replSet shard2ReplSet --port 27018 --bind_ip_all
ports:
- "27028:27018"
volumes:
- shard2db:/data/db
mongos:
container_name: mongos
image: mongo:4.4
restart: always
depends_on:
- configsvr
- shard1
- shard2
command: >
mongos --configdb configReplSet/configsvr:27019 --bind_ip_all --port 27017
ports:
- "27017:27017"
volumes:
configdb: {}
shard1db: {}
shard2db: {}
===== Persistència i reinici automàtic =====
S’utilitzen volums Docker per mantenir les dades persistents encara que els contenidors s’aturin o es recreïn.
Sense volums, la pèrdua dels contenidors implicaria la pèrdua de totes les dades del cluster.
També s’ha configurat:
restart: always
Aquesta directiva permet reiniciar automàticament els contenidors després d’un reinici del sistema o de la màquina.
===== Inicialitzar els contenidors =====
docker-compose up -d
docker ps
===== Inicialitzar el Config Server =====
Accedir al contenidor:
docker exec -it configsvr mongo --port 27019
Inicialitzar el Replica Set:
rs.initiate({
_id: "configReplSet",
configsvr: true,
members: [
{ _id: 0, host: "configsvr:27019" }
]
})
===== Inicialitzar shard1 =====
Accedir al contenidor:
docker exec -it shard1 mongo --port 27018
Inicialitzar el Replica Set:
rs.initiate({
_id: "shard1ReplSet",
members: [
{ _id: 0, host: "shard1:27018" }
]
})
===== Inicialitzar shard2 =====
Accedir al contenidor:
docker exec -it shard2 mongo --port 27018
Inicialitzar el Replica Set:
rs.initiate({
_id: "shard2ReplSet",
members: [
{ _id: 0, host: "shard2:27018" }
]
})
===== Afegir shards al cluster =====
Connectar al router ''mongos'':
docker exec -it mongos mongo --port 27017
Afegir els shards:
sh.addShard("shard1ReplSet/shard1:27018")
sh.addShard("shard2ReplSet/shard2:27018")
===== Activar sharding =====
Activar el ''sharding'' sobre la base de dades:
sh.enableSharding("testDB")
===== Configurar la col·lecció =====
La següent instrucció activa el ''sharding'' sobre la col·lecció ''users'' de la base de dades ''testDB'':
sh.shardCollection(
"testDB.users",
{ _id: "hashed" }
)
On:
* ''testDB.users'' és la col·lecció que es distribuirà entre shards,
* ''_id'' és el camp utilitzat com a ''Shard Key'',
* ''"hashed"'' indica que MongoDB aplicarà una funció hash sobre el valor de ''_id'' per repartir les dades de manera uniforme entre els shards.
===== Inserir dades =====
Crear la base de dades, la col·lecció i inserir les dades (en el mongos):
use testDB
for (let i = 0; i < 1000; i++) {
db.users.insert({
name: "user" + i,
value: i
})
}
===== Comprovar la distribució =====
db.users.getShardDistribution()
Amb aquesta comanda es pot veure els percentatges de distribució
També es pot entrar a cada shard, entrar a la base de dades i veure el contingut de la col·lecció
===== Consultar la configuració =====
use config
db.collections.find({
_id: "testDB.users"
})
===== Limitacions de l’entorn =====
Aquest exemple implementa un cluster ''sharded'' funcional de MongoDB orientat a proves i laboratoris.
Cal tenir en compte que:
* tots els contenidors s’executen sobre una única màquina,
* els shards no estan distribuïts físicament,
* només s’utilitzen dos shards,
* cada shard disposa d’un únic node,
* no s’han configurat rèpliques per alta disponibilitat.
Per tal de poder observar millor els beneficis del ''hash-based sharding'', és recomanable ampliar l’entorn amb més shards, ja que amb pocs nodes la distribució de dades no és prou representativa.
En un entorn de producció:
* cada shard acostuma a executar-se en servidors diferents,
* els shards solen implementar-se mitjançant Replica Sets,
* s’utilitzen mecanismes de monitoratge i tolerància a fallades.
===== Conclusions =====
El ''sharding'' permet escalar MongoDB distribuint les dades entre múltiples nodes.
L’ús de ''hashed shard keys'' facilita:
* el balanceig automàtic,
* la distribució uniforme,
* la reducció de hotspots.