====== 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.