MongDB Sharding¶
Définition¶
C'est une méthode de distribution des données sur plusieurs machines (cluster). Elle permet à MongoDB de passer à l'échelle pour accueillir des bases de données massives avec un débit très important.
Elle fait partie des techniques de mise à l'échelle horizontale : Horizontal scaling.
shard : éclat, tesson (fragment)
Principe de fonctionnement¶
Le cluster est composé de 3 types de serveurs :
- mongos : routeur pour l'acheminement des requêtes.
- Config Server : enregistre les métadonnées sur et la configuration pour le cluster.
- Shard : contient un sous ensemble des données (chunk ou partition) qui peut être déployé comme Replica Set.
La distribution des données sur le cluster est basée sur une clé shard key. La clé peut être un ou plusieurs champs. Elle est utilisée dans l'une des deux stratégies de distribution :
- Hashed Sharding : un hash de clé détermine quelle dans quelle chunk mettre les données.
- Ranged Sharding : la clé est affecté à un chunk selon valeur.
Hashed Sharding | Ranged Sharding |
---|---|
Réplication et Sharding avec Docker¶
Le cluster à mettre en place est compsée des noeuds suivants :
- 2 Mongos (router): routage des requêtes vers les shards.
router01
router02
- 3 Config Servers : enregistre les métadonnées de la configuration du cluster
configsvr01
configsvr02
configsvr03
- 3 Shards (avec un replica set de 3 membres) : détient une partie (shard) des données.
shard01-a
,shard01-b
,shard01-c
shard02-a
,shard02-b
,shard02-c
shard03-a
,shard03-b
,shard03-c
docker-compose sera utilisé pour automatiser la gestion des différents containers (14 dans notre cas). Les fichiers nécessaires à cette manipulation sont mis dans cette archive mongodb-cluster.zip que vous devez télécharger et décompresser.
Vous obtiendrez un dossier contenant :
docker-compose.yaml
qui contient les paramètres des différents containers :
version: '3'
services:
# Router
## router 01
router01:
image: mongo:6.0.1
container_name: router-01
command: |
mongos --port 27017 --configdb rs-config-server/configsvr01:27017,configsvr02:27017,configsvr03:27017 --bind_ip_all
ports:
- 27117:27017
volumes:
- ./scripts:/scripts
## router 02
router02:
image: mongo:6.0.1
container_name: router-02
command: |
mongos --port 27017 --configdb rs-config-server/configsvr01:27017,configsvr02:27017,configsvr03:27017 --bind_ip_all
volumes:
- ./scripts:/scripts
ports:
- 27118:27017
links:
- router01
# Config Servers
## Config server 01
configsvr01:
image: mongo:6.0.1
container_name: mongo-config-01
command: |
mongod --port 27017 --configsvr --replSet rs-config-server
volumes:
- ./scripts:/scripts
ports:
- 27119:27017
links:
- shard01-a
- shard02-a
- shard03-a
## Config server 02
configsvr02:
image: mongo:6.0.1
container_name: mongo-config-02
command: |
mongod --port 27017 --configsvr --replSet rs-config-server
volumes:
- ./scripts:/scripts
ports:
- 27120:27017
links:
- configsvr01
## Config server 03
configsvr03:
image: mongo:6.0.1
container_name: mongo-config-03
command: |
mongod --port 27017 --configsvr --replSet rs-config-server
volumes:
- ./scripts:/scripts
ports:
- 27121:27017
links:
- configsvr02
# Shards
## Shards 01
shard01-a:
image: mongo:6.0.1
container_name: shard-01-a
command: |
mongod --port 27017 --shardsvr --replSet rs-shard-01
volumes:
- ./scripts:/scripts
ports:
- 27122:27017
links:
- shard01-b
- shard01-c
shard01-b:
image: mongo:6.0.1
container_name: shard-01-b
command: |
mongod --port 27017 --shardsvr --replSet rs-shard-01
volumes:
- ./scripts:/scripts
ports:
- 27123:27017
shard01-c:
image: mongo:6.0.1
container_name: shard-01-c
command: |
mongod --port 27017 --shardsvr --replSet rs-shard-01
volumes:
- ./scripts:/scripts
ports:
- 27124:27017
## Shards 02
shard02-a:
image: mongo:6.0.1
container_name: shard-02-a
command: |
mongod --port 27017 --shardsvr --replSet rs-shard-02
volumes:
- ./scripts:/scripts
ports:
- 27125:27017
links:
- shard02-b
- shard02-c
shard02-b:
image: mongo:6.0.1
container_name: shard-02-b
command: |
mongod --port 27017 --shardsvr --replSet rs-shard-02
volumes:
- ./scripts:/scripts
ports:
- 27126:27017
shard02-c:
image: mongo:6.0.1
container_name: shard-02-c
command: |
mongod --port 27017 --shardsvr --replSet rs-shard-02
volumes:
- ./scripts:/scripts
ports:
- 27127:27017
## Shards 03
shard03-a:
image: mongo:6.0.1
container_name: shard-03-a
command: |
mongod --port 27017 --shardsvr --replSet rs-shard-03
volumes:
- ./scripts:/scripts
ports:
- 27128:27017
links:
- shard03-b
- shard03-c
shard03-b:
image: mongo:6.0.1
container_name: shard-03-b
command: |
mongod --port 27017 --shardsvr --replSet rs-shard-03
volumes:
- ./scripts:/scripts
ports:
- 27129:27017
shard03-c:
image: mongo:6.0.1
container_name: shard-03-c
command: |
mongod --port 27017 --shardsvr --replSet rs-shard-03
volumes:
- ./scripts:/scripts
ports:
- 27130:27017
- Un dossier
scripts
contenant les scripts d'initialisation de replica set et shards, les routeurs et les serveurs de configuration.
Démarrer la pile de containers
docker-compose up -d
Initialiser les serveurs de configuration
docker-compose exec configsvr01 sh -c "mongosh < /scripts/configserver.js"
Initialiser les shards
docker-compose exec shard01-a sh -c "mongosh < /scripts/replicaset_1.js"
docker-compose exec shard02-a sh -c "mongosh < /scripts/replicaset_2.js"
docker-compose exec shard03-a sh -c "mongosh < /scripts/replicaset_3.js"
Attendre l'élection des primary puis initialiser les routeurs
docker-compose exec router01 sh -c "mongosh < /scripts/router.js"
-
Vérifier la réplication
et ensuitedocker-compose exec shard01-a mongosh
rs.status()
-
Vérifier les shards
et ensuitedocker-compose exec router01 mongosh
sh.status()
Distribuer une base de données
- Créer une nouvelle base et nouvelle collection. Puis créer un index sur _id.
> use testDB;
> sh.enableSharding("testDB");
> db.createCollection("test");
> db.test.createIndex({"_id":"hashed"});
> sh.shardCollection("testDB.test",{"_id":"hashed"});
mongoimport -d testDB -c test --port 27017 restaurants.json
mongosh --port 27017 --eval "sh.status()"
Attention
Les requêtes sont destinées au routeur.
- Inspecter les propriétés et déterminer :
- La clé de sharding
- Le nombre de shunks par shard
Vérifier la distribution des documents sur les shards : sur le router, exécuter les commandes :
use testDB
db.test.getShardDistribution()
Voici un exemple de sortie :
[direct: mongos] test> use testDB
switched to db testDB
[direct: mongos] testDB> db.test.getShard
db.test.getShardVersion db.test.getShardDistribution
[direct: mongos] testDB> db.test.getShardDistribution()
Shard rs-shard-02 at rs-shard-02/shard02-a:27017,shard02-b:27017,shard02-c:27017
{
data: '3.66MiB',
docs: 8501,
chunks: 2,
'estimated data per chunk': '1.83MiB',
'estimated docs per chunk': 4250
}
---
Shard rs-shard-03 at rs-shard-03/shard03-a:27017,shard03-b:27017,shard03-c:27017
{
data: '3.64MiB',
docs: 8414,
chunks: 2,
'estimated data per chunk': '1.82MiB',
'estimated docs per chunk': 4207
}
---
Shard rs-shard-01 at rs-shard-01/shard01-a:27017,shard01-b:27017,shard01-c:27017
{
data: '3.65MiB',
docs: 8442,
chunks: 2,
'estimated data per chunk': '1.82MiB',
'estimated docs per chunk': 4221
}
---
Totals
{
data: '10.95MiB',
docs: 25357,
chunks: 6,
'Shard rs-shard-02': [
'33.46 % data',
'33.52 % docs in cluster',
'452B avg obj size on shard'
],
'Shard rs-shard-03': [
'33.22 % data',
'33.18 % docs in cluster',
'453B avg obj size on shard'
],
'Shard rs-shard-01': [
'33.31 % data',
'33.29 % docs in cluster',
'453B avg obj size on shard'
]
}
Isolation et cohérence¶
Dans ce quit, nous configurons les niveaux de cohérence avec les paramètres readConcern et writeConcern.
Se connecter à un routeur
docker-compose exec -it router01 mongosh
readConcern
use testDB;
db.test.find({}).readConcern("majority");
writeConcern
try {
db.test.updateMany(
{ "name" : "Windy's" },
{ $inc: { "violations" : 3}, $set: { "Closed" : true } },
{ w: "majority", wtimeout: 100 }
);
} catch (e) {
print(e);
}