Guide étape par étape : Déploiement d'un cluster fragmenté MongoDB de base

Déployez un cluster fragmenté MongoDB de base avec des serveurs de configuration, des jeux de réplicas de fragments, des routeurs mongos et une vérification du partitionnement.

Guide étape par étape : Déploiement d'un cluster fragmenté MongoDB de base

MongoDB, une base de données documentaire NoSQL populaire, excelle dans le traitement de grands volumes de données avec des performances élevées et une grande flexibilité. Cependant, à mesure que les données croissent, un seul serveur ou jeu de réplicas peut atteindre ses limites de mise à l'échelle. C'est là que le partitionnement (sharding) entre en jeu, permettant une scalabilité horizontale en distribuant les données sur plusieurs serveurs, ou fragments.

Ce guide vous accompagne dans la mise en place d'un cluster fragmenté MongoDB de base sur localhost à des fins d'apprentissage. Vous configurerez des serveurs de configuration, des jeux de réplicas de fragments et un routeur mongos, puis activerez le partitionnement pour une collection.

Comprendre les clusters fragmentés MongoDB

Un cluster fragmenté MongoDB se compose de trois composants principaux qui travaillent ensemble pour distribuer et router les données :

  • Jeux de réplicas de fragments (Shard Replica Sets) : Ce sont les nœuds réels contenant les données. Chaque fragment est un jeu de réplicas pour assurer une haute disponibilité et une redondance des données. Les données sont partitionnées entre ces fragments.
  • Serveurs de configuration (Config Servers) : Ils stockent les métadonnées du cluster, y compris le mappage des morceaux de données (chunks) vers les fragments. À partir de MongoDB 3.2, les serveurs de configuration doivent être déployés en tant que jeu de réplicas (CSRS - Config Server Replica Set) pour la haute disponibilité et la cohérence.
  • Routeurs mongos : Ils agissent comme des routeurs de requêtes, fournissant une interface pour les applications clientes. Une instance mongos dirige les opérations client vers le(s) fragment(s) approprié(s) en fonction des métadonnées du cluster. Les applications se connectent à mongos, pas directement aux fragments.

Diagramme d'architecture d'un cluster fragmenté MongoDB (conceptuel) Diagramme conceptuel d'un cluster fragmenté MongoDB (crédit image : documentation officielle MongoDB)

Prérequis

Avant de commencer, assurez-vous d'avoir les éléments suivants :

  1. Plusieurs machines/VM : Pour un cluster fragmenté véritablement distribué, vous aurez besoin d'au moins 6 à 9 machines/VM/conteneurs Docker. Pour ce tutoriel de base, nous pouvons simuler cela sur une seule machine en utilisant différents ports, mais rappelez-vous qu'une configuration de production nécessite des ressources dédiées.
    • 3 pour les serveurs de configuration (configSrv01, configSrv02, configSrv03)
    • Minimum 2-3 pour chaque fragment (par exemple, Shard01-RS01, Shard01-RS02, Shard01-RS03 ; Shard02-RS01, ...)
    • 1+ pour les routeurs mongos
  2. Installation de MongoDB : Installez une version prise en charge du serveur MongoDB sur chaque machine qui hébergera mongod ou mongos. Utilisez mongosh pour les commandes shell.
  3. Réseau : Assurez-vous que toutes les machines peuvent communiquer entre elles sur les ports nécessaires (par défaut 27017, 27018, 27019, 27020 pour les serveurs de configuration, les fragments et mongos respectivement, ou des ports personnalisés).
  4. Structure de répertoires : Créez des répertoires de données et de journaux dédiés pour chaque instance mongod et mongos.

Pour simplifier dans ce guide, nous utiliserons localhost avec différents ports et répertoires. Dans un environnement de production, vous utiliseriez des noms d'hôte ou des adresses IP réels.

Structure de répertoires recommandée (Exemple pour une configuration localhost)

mkdir -p /data/db/configdb01 /data/db/configdb02 /data/db/configdb03
mkdir -p /data/db/shard01-rs01 /data/db/shard01-rs02 /data/db/shard01-rs03
mkdir -p /data/db/shard02-rs01 /data/db/shard02-rs02 /data/db/shard02-rs03
mkdir -p /data/log/config /data/log/shard01 /data/log/shard02 /data/log/mongos

Étapes de déploiement

Étape 1 : Configurer les serveurs de configuration (Jeu de réplicas de configuration)

Les serveurs de configuration stockent les métadonnées du cluster fragmenté. Ils doivent fonctionner en tant que jeu de réplicas.

  1. Démarrer les instances mongod pour les serveurs de configuration : Chaque instance nécessite les options --configsvr et --replSet.

    # Serveur de configuration 1
    mongod --configsvr --replSet cfgReplSet --dbpath /data/db/configdb01 --port 27019 --bind_ip localhost --logpath /data/log/config/configdb01.log --fork
    
    # Serveur de configuration 2
    mongod --configsvr --replSet cfgReplSet --dbpath /data/db/configdb02 --port 27020 --bind_ip localhost --logpath /data/log/config/configdb02.log --fork
    
    # Serveur de configuration 3
    mongod --configsvr --replSet cfgReplSet --dbpath /data/db/configdb03 --port 27021 --bind_ip localhost --logpath /data/log/config/configdb03.log --fork
    

    Astuce : Pour la production, remplacez localhost par des adresses IP ou des noms d'hôte réels.

  2. Initialiser le jeu de réplicas de configuration : Connectez-vous à l'une des instances de serveur de configuration et initialisez le jeu de réplicas.

    mongosh --port 27019
    

    Dans le shell mongo :

    rs.initiate({
       _id: "cfgReplSet",
       configsvr: true,
       members: [
          { _id : 0, host : "localhost:27019" },
          { _id : 1, host : "localhost:27020" },
          { _id : 2, host : "localhost:27021" }
       ]
    });
    

    Vérifiez le statut :

    rs.status();
    

Étape 2 : Configurer les jeux de réplicas de fragments

Chaque fragment du cluster est un jeu de réplicas. Nous allons configurer deux fragments (shard01 et shard02), chacun avec trois membres.

  1. Démarrer les instances mongod pour les membres du Fragment 1 : Chaque instance nécessite les options --shardsvr et --replSet.

    # Fragment 1 Membre 1
    mongod --shardsvr --replSet shard01 --dbpath /data/db/shard01-rs01 --port 27030 --bind_ip localhost --logpath /data/log/shard01/shard01-rs01.log --fork
    
    # Fragment 1 Membre 2
    mongod --shardsvr --replSet shard01 --dbpath /data/db/shard01-rs02 --port 27031 --bind_ip localhost --logpath /data/log/shard01/shard01-rs02.log --fork
    
    # Fragment 1 Membre 3
    mongod --shardsvr --replSet shard01 --dbpath /data/db/shard01-rs03 --port 27032 --bind_ip localhost --logpath /data/log/shard01/shard01-rs03.log --fork
    
  2. Initialiser le jeu de réplicas du Fragment 1 : Connectez-vous à l'une des instances du Fragment 1.

    mongosh --port 27030
    

    Dans le shell mongo :

    rs.initiate({
       _id : "shard01",
       members: [
          { _id : 0, host : "localhost:27030" },
          { _id : 1, host : "localhost:27031" },
          { _id : 2, host : "localhost:27032" }
       ]
    });
    
  3. Démarrer les instances mongod pour les membres du Fragment 2 (répétez pour les fragments supplémentaires) :

    # Fragment 2 Membre 1
    mongod --shardsvr --replSet shard02 --dbpath /data/db/shard02-rs01 --port 27040 --bind_ip localhost --logpath /data/log/shard02/shard02-rs01.log --fork
    
    # Fragment 2 Membre 2
    mongod --shardsvr --replSet shard02 --dbpath /data/db/shard02-rs02 --port 27041 --bind_ip localhost --logpath /data/log/shard02/shard02-rs02.log --fork
    
    # Fragment 2 Membre 3
    mongod --shardsvr --replSet shard02 --dbpath /data/db/shard02-rs03 --port 27042 --bind_ip localhost --logpath /data/log/shard02/shard02-rs03.log --fork
    
  4. Initialiser le jeu de réplicas du Fragment 2 : Connectez-vous à l'une des instances du Fragment 2.

    mongosh --port 27040
    

    Dans le shell mongo :

    rs.initiate({
       _id : "shard02",
       members: [
          { _id : 0, host : "localhost:27040" },
          { _id : 1, host : "localhost:27041" },
          { _id : 2, host : "localhost:27042" }
       ]
    });
    

Étape 3 : Configurer les routeurs mongos

Les instances mongos sont les points d'entrée pour les applications clientes. Elles doivent connaître l'emplacement des serveurs de configuration.

  1. Démarrer les instances mongos : Fournissez l'option --configdb, listant les membres du jeu de réplicas de configuration.

    # Routeur Mongos 1
    mongos --configdb cfgReplSet/localhost:27019,localhost:27020,localhost:27021 --port 27017 --bind_ip localhost --logpath /data/log/mongos/mongos01.log --fork
    

    Remarque : Vous pouvez démarrer plusieurs instances mongos pour l'équilibrage de charge et la haute disponibilité. Elles se connectent toutes aux mêmes serveurs de configuration.

Étape 4 : Se connecter à mongos et ajouter des fragments

Maintenant, connectez-vous à une instance mongos et ajoutez les jeux de réplicas de fragments au cluster.

  1. Se connecter à mongos : Utilisez le port MongoDB par défaut 27017 ou le port personnalisé que vous avez spécifié pour mongos.

    mongosh --port 27017
    
  2. Ajouter des fragments : Utilisez la commande sh.addShard(), en spécifiant le nom du jeu de réplicas et l'un de ses membres.

    sh.addShard("shard01/localhost:27030");
    sh.addShard("shard02/localhost:27040");
    

Étape 5 : Activer le partitionnement pour une base de données et une collection

Une fois les fragments ajoutés, vous devez activer le partitionnement pour des bases de données spécifiques, puis pour des collections spécifiques au sein de ces bases de données. Cela nécessite de choisir une clé de partitionnement (shard key).

  1. Activer le partitionnement pour une base de données : Basculez vers la base de données que vous souhaitez partitionner et exécutez sh.enableSharding().

    use mydatabase;
    sh.enableSharding("mydatabase");
    
  2. Partitionner une collection : Choisissez une clé de partitionnement et utilisez sh.shardCollection().

    Avertissement : Choisir une clé de partitionnement efficace est crucial pour les performances et une distribution uniforme. Une mauvaise clé de partitionnement peut entraîner des points chauds ou des requêtes inefficaces. Les stratégies courantes incluent les clés hachées, les clés par plage ou les clés composées.

    Pour cet exemple, supposons une collection mycollection avec un champ _id.

    sh.shardCollection("mydatabase.mycollection", { _id: "hashed" });
    

    Une clé de partitionnement hachée _id est simple pour un tutoriel car elle répartit mieux les insertions entre les fragments qu'une clé _id par plage monotone croissante. Pour une application réelle, choisissez la clé de partitionnement en fonction de vos modèles de requêtes et de la distribution des écritures, pas uniquement par commodité.

Étape 6 : Vérifier le cluster

Exécutez ces commandes depuis mongosh connecté à mongos :

sh.status();
db.adminCommand({ listShards: 1 });

Ensuite, insérez des documents d'exemple et vérifiez que la collection partitionnée existe :

use mydatabase;
db.mycollection.insertMany([
  { _id: 1, name: "alpha" },
  { _id: 2, name: "beta" },
  { _id: 3, name: "gamma" }
]);

db.mycollection.getShardDistribution();

Les petits ensembles de données de test peuvent ne pas se diviser immédiatement, ne vous attendez donc pas à une distribution parfaite après seulement quelques documents. La première vérification importante est que sh.status() liste les deux fragments et montre que mydatabase.mycollection est partitionnée.

Notes pour la production

Cette configuration localhost est utile pour apprendre les composants, mais la production nécessite plus de soin :

  • Utilisez de vrais noms d'hôte, pas localhost, car les noms des membres du jeu de réplicas sont stockés dans les métadonnées du cluster.
  • Exécutez les serveurs de configuration en tant que jeu de réplicas à trois membres.
  • Exécutez chaque fragment en tant que jeu de réplicas avec des membres répartis sur des domaines de défaillance.
  • Activez l'authentification et l'authentification interne par fichier de clé ou x.509 avant d'exposer le cluster.
  • Sauvegardez les métadonnées du serveur de configuration et les données des fragments dans le cadre d'un plan de sauvegarde unique prenant en compte le cluster.
  • Surveillez la distribution des morceaux, l'activité de l'équilibreur, le retard de réplication et la croissance des disques.

Conclusion

Un cluster fragmenté MongoDB a trois tâches : les serveurs de configuration suivent les métadonnées, les jeux de réplicas de fragments stockent les données, et mongos route le trafic client. Faites fonctionner ces rôles d'abord, puis consacrez la majeure partie de votre temps de conception à la clé de partitionnement, car ce choix détermine si votre cluster répartit la charge proprement ou crée des fragments chauds.