Un replica set MongoDB se compose d'un nœud primaire et de plusieurs nœuds secondaires. Toutes les écritures sont dirigées vers le primaire, tandis que les secondaires répliquent les données pour maintenir des jeux de données identiques et assurer la haute disponibilité.
Le schéma ci-dessous, issu de la documentation officielle MongoDB, illustre un replica set typique constitué d'un primaire et de deux secondaires.
Élection du primaire
Initialisez un replica set avec replSetInitiate ou rs.initiate(). Une fois initialisés, les membres échangent des signaux de présence (heartbeats) et élisent un primaire. Le nœud qui obtient la majorité des votes devient primaire ; les autres deviennent secondaires.
Initialiser un replica set
config = {
_id : "my_replica_set",
members : [
{_id : 0, host : "rs1.example.net:27017"},
{_id : 1, host : "rs2.example.net:27017"},
{_id : 2, host : "rs3.example.net:27017"},
]
}
rs.initiate(config)
Définition de la « majorité »
Pour N membres votants, la majorité correspond à N/2 + 1. Si moins d'une majorité de membres sont actifs, le replica set ne peut pas élire de primaire et passe en mode lecture seule.
|
Nombre de membres votants |
Majorité requise |
Nombre de pannes tolérées |
|
1 |
1 |
0 |
|
2 |
2 |
0 |
|
3 |
2 |
1 |
|
4 |
3 |
1 |
|
5 |
3 |
2 |
|
6 |
4 |
2 |
|
7 |
4 |
3 |
Privilégiez un nombre impair de membres. Bien qu'un replica set de trois nœuds et un de quatre nœuds ne tolèrent tous deux qu'une seule panne, l'ajout d'un quatrième nœud offre une meilleure fiabilité pour le stockage des données.
Types spécifiques de nœuds secondaires
Par défaut, un nœud secondaire participe aux élections, peut devenir primaire et synchronise les données depuis le primaire afin de maintenir un jeu de données identique.
Les secondaires peuvent également traiter les requêtes de lecture pour augmenter la capacité de lecture. MongoDB prend en charge plusieurs types de secondaires spécialisés adaptés à différents scénarios.
-
Arbiter
Un arbiter ne participe qu'aux votes lors des élections. Il ne peut jamais devenir primaire et ne stocke aucune donnée.
Dans un replica set à deux nœuds, la défaillance de l'un d'eux empêche l'élection d'un primaire. L'ajout d'un arbiter permet aux élections de réussir même si l'un des nœuds contenant des données est indisponible.
Étant légers (aucun stockage de données), les arbiters sont idéaux pour les replica sets comportant un nombre pair de membres.
-
Priority0
Un nœud avec une priorité de 0 ne peut pas être élu primaire.
Par exemple, dans un déploiement multi-centres de données, définissez la priorité des membres du centre de données B à 0 pour garantir que le primaire reste toujours dans le centre de données A.
RemarqueLa majorité des nœuds doit se trouver dans le centre de données A. Sinon, aucune élection de primaire ne pourra avoir lieu en cas de partitionnement réseau.
-
Vote 0
Avec MongoDB 3.0, un replica set peut compter jusqu'à 50 membres, mais seuls sept d'entre eux ont le droit de vote. Les membres non votants (Vote0) doivent avoir leur propriété
votedéfinie sur 0. -
Hidden
Un nœud hidden possède une priorité de 0 et reste invisible pour le pilote (driver).
Ces nœuds sont parfaits pour les sauvegardes de données ou le traitement hors ligne, car ils ne répondent pas aux requêtes clients.
-
Delayed
Un nœud delayed est un nœud hidden dont les données accusent un retard configurable par rapport au primaire, par exemple une heure.
Ce type de nœud permet une récupération à un instant donné (point-in-time recovery) en cas d'écriture incorrecte de données sur le primaire.
Réélection du primaire
Outre l'initialisation, une réélection du primaire se produit dans les situations suivantes :
-
Reconfiguration du replica set
Une réélection est déclenchée lorsqu'un secondaire détecte que le primaire est hors ligne, ou lorsque le primaire se retire volontairement. Le résultat dépend des heartbeats, de la priorité et de l'horodatage le plus récent de l'oplog.
-
Priorité des nœuds
Les nœuds votent pour le candidat ayant la priorité la plus élevée. Un nœud avec une priorité de 0 ne lance jamais d'élection. Si le primaire découvre un secondaire avec une priorité supérieure et un retard de données inférieur à 10 secondes, il se retire pour laisser ce secondaire prendre le relais.
-
Optime
Seul le nœud disposant de l'optime la plus récente (l'horodatage de la dernière entrée de l'oplog) peut être élu primaire.
-
-
Partitionnement réseau
Un nœud ne peut devenir primaire que s'il se connecte à une majorité de nœuds votants. Si le primaire perd sa connexion avec la majorité, il rétrograde au statut de secondaire. Lors d'un partitionnement réseau, plusieurs primaires peuvent coexister brièvement. Définissez le write concern sur majority pour garantir qu'un seul primaire puisse finaliser les écritures avec succès.
Synchronisation des données
La synchronisation des données du primaire vers les secondaires repose sur un oplog. Chaque écriture sur le primaire génère une entrée dans la collection local.oplog.rs. Les secondaires récupèrent et appliquent continuellement les nouvelles entrées de l'oplog.
La collection local.oplog.rs est limitée en taille : lorsqu'elle atteint sa limite, les entrées les plus anciennes sont supprimées. Les entrées de l'oplog sont idempotentes — leur réapplication produit le même résultat — car elles peuvent être appliquées plusieurs fois sur les secondaires.
Une entrée d'oplog suit le format suivant :
{
"ts" : Timestamp(1446011584, 2),
"h" : NumberLong("1687359108795812092"),
"v" : 2,
"op" : "i",
"ns" : "test.nosql",
"o" : { "_id" : ObjectId("563062c0b085733f34ab4129"), "name" : "mongodb", "score" : "100" }
}
Champs :
ts : L'heure de l'opération, correspondant à l'horodatage UNIX actuel plus un compteur. Le compteur est réinitialisé chaque seconde.
h : Un identifiant globalement unique pour l'opération.
v : Les informations de version de l'oplog.
-
op : Le type d'opération. Les valeurs valides sont :
i : Opération d'insertion.
u : Opération de mise à jour.
d : Opération de suppression.
c : Exécution d'une commande, telle que
createDatabaseoudropDatabase.n : Opération nulle. Utilisée à des fins spéciales.
ns : La collection ciblée par l'opération.
o : Le contenu de l'opération.
o2 : La condition de requête pour l'opération. Ce champ n'est inclus que pour les opérations de mise à jour.
Lors de son premier raccordement, un secondaire effectue une synchronisation initiale (init sync), en copiant l'intégralité du jeu de données depuis le primaire ou depuis un secondaire plus à jour. Par la suite, il utilise un tailable cursor pour récupérer et appliquer continuellement les nouvelles entrées de l'oplog depuis la collection local.oplog.rs du nœud primaire.
Le processus init sync se déroule comme suit :
À T1, le secondaire copie toutes les bases de données (à l'exception de
local) depuis le primaire en utilisantlistDatabases,listCollectionsetcloneCollection. Supposons que toutes les opérations soient terminées à T2.Le secondaire applique toutes les entrées de l'oplog générées entre T1 et T2. Certaines peuvent chevaucher celles de l'étape 1, mais la réapplication est sans risque car les entrées de l'oplog sont idempotentes.
-
Le secondaire crée les index selon la configuration du primaire. L'index
_idde chaque collection a déjà été créé lors de l'étape 1.RemarqueDimensionnez l'oplog en fonction de la taille de votre base de données et du volume d'écritures. Si l'oplog est trop volumineux, vous gaspillez de l'espace de stockage. S'il est trop petit,
init syncrisque de ne jamais aboutir : si la base de données est importante, l'oplog pourrait ne pas conserver toutes les entrées entre T1 et T2, ce qui entraînerait l'échec de la synchronisation.
Modifier la configuration du replica set
Pour ajouter ou supprimer des membres, ou modifier des propriétés telles que priority, vote, hidden ou delayed, utilisez replSetReconfig ou rs.reconfig().
Par exemple, pour définir la priorité du deuxième membre sur 2 :
cfg = rs.conf();
cfg.members[1].priority = 2;
rs.reconfig(cfg);
Gestion des erreurs (Rollback)
Si le primaire tombe en panne avec des données non synchronisées et que des écritures surviennent sur le nouveau primaire avant que l'ancien ne se reconnecte, l'ancien primaire annule (rollback) ses opérations non synchronisées pour s'aligner sur le jeu de données du nouveau primaire.
Les données annulées sont enregistrées dans un répertoire de rollback. Les administrateurs peuvent les récupérer à l'aide de mongorestore si nécessaire.
Paramètres de lecture et d'écriture
-
Read Preference
Par défaut, toutes les lectures sont dirigées vers le primaire. Configurez la read preference dans le pilote pour router les lectures vers d'autres nœuds.
primary : Mode par défaut. Toutes les lectures vont au primaire.
primaryPreferred : Lecture depuis le primaire ; bascule vers les secondaires si le primaire est inaccessible.
secondary : Toutes les lectures vont aux secondaires.
secondaryPreferred : Lecture depuis les secondaires ; bascule vers le primaire si tous les secondaires sont inaccessibles.
nearest : Lecture depuis le nœud accessible le plus proche, déterminé par la latence du
ping.
-
Write Concern
Par défaut, le primaire renvoie une réponse après avoir terminé une écriture. Configurez le Write Concern dans le pilote pour définir les règles de réussite des écritures.
L'exemple suivant exige qu'une écriture réussisse sur une majorité de nœuds dans un délai de 5 secondes.
db.products.insert( { item: "envelopes", qty : 100, type: "Clasp" }, { writeConcern: { w: "majority", wtimeout: 5000 } } )La méthode précédente s'applique à une seule requête. Pour définir le write concern par défaut pour l'ensemble du replica set :
cfg = rs.conf() cfg.settings = {} cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 } rs.reconfig(cfg)