La réplication MongoDB (copie) définit le combat réel et son analyse de principe-04

Ensemble de réplicas MongoDB

Architecture d'ensemble de répliques

Dans un environnement de production, il n'est pas recommandé d'utiliser un serveur MongoDB autonome. Les raisons sont les suivantes:
       La version autonome de MongoDB ne peut garantir la fiabilité, une fois que le processus échoue ou que le serveur tombe en panne, l'entreprise sera directement indisponible.
        Une fois que le disque du serveur est endommagé, les données seront directement perdues et aucune copie n'est disponible pour le moment. 
L'ensemble de réplication Mongodb (ensemble de réplication) se compose d'un groupe d'instances Mongod (processus), comprenant un nœud principal et plusieurs nœuds secondaires. Toutes les données du pilote Mongodb (client) sont écrites sur le primaire et le secondaire synchronise les données écrites. Afin que tous les membres du jeu de répliques stockent le même jeu de données, une haute disponibilité des données est fournie. Les jeux de réplicas offrent une redondance et une haute disponibilité et constituent la base de tous les déploiements de production. Sa réalité dépend de la fonctionnalité de deux aspects :
       1. Lorsque les données sont écrites, les données sont rapidement copiées vers un autre nœud indépendant
       2. Lorsque le nœud recevant l'écriture échoue, un nouveau nœud de remplacement est automatiquement élu
Tout en atteignant une haute disponibilité, le jeu de répliques réalise plusieurs autres fonctions supplémentaires :
Distribution des données  : copier les données d'une région à une autre, réduisant ainsi la latence de lecture dans une autre région
Séparation lecture-écriture : Différents types de pression sont exécutés sur différents nœuds
Reprise après sinistre hors site : passez rapidement hors site lorsque le centre de données tombe en panne
Mode jeu de répliques à trois nœuds
Une architecture de jeu de répliques commune se compose de 3 nœuds membres, dont il existe plusieurs modes différents.
Mode PSS (mode officiel recommandé)
Le mode PSS se compose d'un nœud principal et de deux nœuds de secours, à savoir Primaire + Secondaire + Secondaire.

Ce mode fournit toujours deux copies complètes du jeu de données. Si le nœud principal n'est pas disponible, le jeu de répliques choisit le nœud de secours comme nœud principal.
Cliquez et continuez le fonctionnement normal. L'ancien nœud principal rejoint le jeu de répliques lorsqu'il devient disponible.

Mode PSA
Le mode PSA se compose d'un nœud maître, d'un nœud de secours et d'un nœud arbitre, à savoir
Primaire + Secondaire + Arbitre

Parmi eux, les nœuds Arbiter ne stockent pas de copies de données et ne fournissent pas d'opérations de lecture et d'écriture professionnelles. La défaillance du nœud arbitre n'affecte pas
affecter les affaires, seulement les votes électoraux. Ce mode ne fournit qu'une seule copie complète des données, et si le nœud principal n'est pas disponible, le
L'ensemble sélectionnera le nœud de secours comme nœud principal

Configuration typique d'un environnement d'ensemble de répliques à trois nœuds
        Même s'il n'y a qu'un seul serveur pour l'instant, démarrez le jeu de répliques en mode nœud unique
        Ensemble de réplication de démarrage multi-instance sur une seule machine
        Jeu de réplicas de démarrage à nœud unique
Considérations sur les jeux de répliques
        À propos du matériel :
                Étant donné que les nœuds de jeu de répliques normaux peuvent devenir des nœuds maîtres, leur état est le même, de sorte que la configuration matérielle doit être cohérente ;
                Afin de s'assurer que les nœuds ne tomberont pas en panne en même temps, le matériel utilisé par chaque nœud doit être indépendant.
        À propos du logiciel :
                La version logicielle de chaque nœud du jeu de répliques doit être cohérente pour éviter des problèmes imprévisibles.
                L'ajout de nœuds n'augmentera pas les performances d'écriture du système
Préparation environnementale
        Installer MongoDB et configurer les variables d'environnement
        Assurez-vous qu'il y a plus de 10 Go d'espace disque
Préparer les fichiers de configuration
        Chaque processus mongod d'un jeu de répliques doit résider sur un serveur différent. Nous exécutons maintenant 3 processus sur une machine, nous devons donc configurer chacun d'eux : Différents ports (28017/28018/28019) Différents répertoires de données
mkdir ‐p /data/db{1,2,3}
Différents chemins de fichiers journaux (par exemple : /data/db1/mongod.log)
Créez un fichier de configuration /data/db1/mongod.conf avec le contenu suivant :
systemLog:
  destination: file
  path: /data/db1/mongod.log # log path
  logAppend: true
storage:
  dbPath: /data/db1 # data directory
net:
  bindIp: 0.0.0.0
  port: 28017 # port
replication:
  replSetName: rs0
processManagement:
  fork: true
Reportez-vous à la configuration ci-dessus pour modifier le port et le chemin, puis configurez db2 et db3 tour à tour. Notez qu'il doit être au format yaml
Démarrer le processus MongoDB
mongod ‐f /data/db1/mongod.conf
mongod ‐f /data/db2/mongod.conf
mongod ‐f /data/db3/mongod.conf
Remarque : Si SELinux est activé, il peut empêcher le démarrage du processus ci-dessus. Pour plus de simplicité, désactivez SELinux
# 永久关闭,将SELINUX=enforcing改为SELINUX=disabled,设置后需要重启才能生效
 vim /etc/selinux/config
# 查看SELINUX
 /usr/sbin/sestatus ‐v
Configurer le jeu de répliques
Le jeu de répliques est initialisé via la commande replSetInitiate ou rs.initiate() du shell mongo. Après l'initialisation, chaque membre commence à envoyer des messages de pulsation et lance une opération d'élection Priamry. Le nœud qui a été voté par "la plupart" des membres sera deviennent primaires, et les nœuds
méthode 1
# mongo ‐‐port 28017
# 初始化复制集
> rs.initiate()
# 将其余成员添加到复制集
> rs.add("192.168.65.174:28018")
> rs.add("192.168.65.174:28019")
Méthode 2
# mongo ‐‐port 28017
 # 初始化复制集
 > rs.initiate({
     _id: "rs0",
     members: [{
             _id: 0,
             host: "192.168.65.174:28017"
         },{
             _id: 1,
             host: "192.168.65.174:28018"
         },{
             _id: 2,
             host: "192.168.65.174:28019"
     }]
 })
vérifier
Nœud principal MongoDB pour les écritures
# mongo ‐‐port 28017
rs0:PRIMARY> db.user.insert([{name:"fox"},{name:"monkey"}])
MongoDB lit à partir du nœud
# mongo ‐‐port 28018
# 指定从节点可读
rs0:SECONDARY> rs.secondaryOk()
rs0:SECONDARY> db.user.find()
Requête sur l'état de l'ensemble de répliques
Affichez l'état général du jeu d'instances dupliquées :
rs.status()
Vous pouvez afficher l'état actuel de chaque membre, y compris s'il est sain, s'il est en synchronisation complète, les informations de pulsation, les informations de synchronisation incrémentielle, les informations d'élection, l'heure du dernier battement de cœur, etc.
La colonne des membres reflète l'état de tous les membres du jeu de répliques, principalement comme suit :
santé : si le membre est en bonne santé ou non, détecté par le rythme cardiaque. state/stateStr : l'état du membre, PRIMARY signifie le nœud principal et SECONDARY signifie le nœud de secours, si le nœud s'éteint
En cas d'échec, un autre état peut apparaître, tel que RECOVERY.
uptime : La disponibilité du membre.
optime/optimeDate : l'heure du dernier oplog synchrone du membre.
optimeDurable/optimeDurableDate : heure du dernier journal d'exécution synchrone du membre.
pingMs : le délai de ping entre le membre et le nœud actuel.
syncingTo : source de synchronisation du membre.

Afficher les rôles de nœud actuels :

db.isMaster()
En plus des informations actuelles sur le rôle du nœud, il s'agit d'informations plus simplifiées et renvoie également la liste des membres de l'ensemble du jeu de réplicas, qui est le véritable principal, les informations de configuration liées au protocole, etc., et le pilote enverra cette commande lors de la première connexion au jeu de répliques.

 Commandes de jeu de répliques de Mongo Shell

commande

décrire

rs . ajouter()

Ajouter de nouveaux nœuds

rs.ad dArb ()

Ajouter un

rs.conf()

Renvoyer les informations de configuration du jeu de répliques

rs.fr eeze ()

Empêcher le nœud actuel d'être élu comme nœud maître pendant un certain temps

rs.help()

Renvoyer  l'aide de la commande pour le jeu de réplicas

rs. initier ()

Initialiser un nouveau jeu de répliques

rs.printReplicationInfo ( )

Renvoie un rapport d'état de la réplication du point de vue du nœud maître

rs.printSeconda ryReplicationInfo ()

Renvoie un rapport sur l'état de la réplication du point de vue du nœud esclave

rs. reconfigurer ()

Mettre à jour la configuration du jeu de répliques en

rs.re déplacer ()

Supprimer un nœud d' un jeu de répliques

rs . secondaireOk ( )

Définit le nœud esclave pour qu'il soit lisible pour la connexion actuelle

rs.st atus ()

Renvoie les informations d'état du jeu de répliques.

rs. stepDown ()

Laisser le primaire actuel devenir un nœud esclave et déclencher l'élection

rs. syncDepuis ()

Définissez le nœud à partir duquel le nœud du jeu de répliques synchronise les données, ce qui remplacera la  logique de sélection par défaut

 Méthode de connexion de l'ensemble de répliques

 

Méthode 2 (fortement recommandée)  : Connectez-vous à MongoDB via un Uri hautement disponible. Lorsque le primaire bascule, le pilote MongoDB peut automatiquement détecter et acheminer le trafic vers le nouveau nœud primaire.

 configuration du jeu de répliques de l'opération springboot

spring:
  data:
  mongodb:
  uri:
mongodb://yanqiuxiang:[email protected]:192.168.30.130:192.168.30.130:28019/test?authSource=admin&replicaSet=rs0
Rôles des membres de l'ensemble de réplicas
Il existe plusieurs nœuds dans le jeu de répliques et chaque nœud a des responsabilités différentes. Avant d'examiner les rôles des membres, comprenez deux attributs importants :
Attribut 1 : Priorité = 0
Lorsque Priority est égal à 0, il ne peut pas être élu maître par le jeu de répliques Plus la valeur de Priority est élevée, plus la probabilité d'être élu maître est grande. Généralement, cette fonctionnalité peut être utilisée pour déployer des jeux de réplicas dans des salles informatiques. En supposant que la salle informatique A et la salle informatique B sont utilisées, puisque l'activité principale est plus proche de la salle informatique A, vous pouvez définir la Priorité du membre du jeu de réplication de la salle informatique B sur 0, de sorte que le nœud maître doit être membre de salle informatique A.
Attribut 2 : Vote = 0
Il ne peut pas participer au vote électoral et la priorité de ce nœud doit également être de 0 à ce moment, c'est-à-dire qu'il ne peut pas être élu en tant que maître. Puisqu'il n'y a que 7 membres votants au maximum dans un jeu de répliques, les membres supplémentaires doivent définir leur valeur d'attribut de vote sur 0, c'est-à-dire que ces membres ne pourront pas participer au vote.
rôle de membre
        Primaire : le nœud principal, qui reçoit toutes les demandes d'écriture, puis synchronise la modification sur tous les nœuds de secours. Un jeu de répliques ne peut avoir qu'un seul nœud maître. Lorsque le nœud maître "se bloque", d'autres nœuds rééliront un nœud maître.
        Secondaire : le nœud de secours conserve le même ensemble de données que le nœud principal. Lorsque le nœud maître "se bloque", il participe à l'élection du nœud maître. Divisé en trois types différents : Hidden = false : nœud normal en lecture seule, s'il peut être sélectionné comme nœud principal et s'il peut voter dépend de la valeur de Priority et Vote ;
        Hidden = true : le nœud caché, invisible pour le client, peut participer à l'élection, mais la priorité doit être 0 , c'est-à-dire qu'il ne peut pas être promu maître. Étant donné que les nœuds masqués n'acceptent pas l'accès professionnel, certaines tâches de sauvegarde de données et de calcul hors ligne peuvent être effectuées via des nœuds masqués, ce qui n'affectera pas l'ensemble du jeu de réplication.
        Delayed : les nœuds retardés doivent avoir les caractéristiques des nœuds cachés et Priority0 en même temps, et seront retardés pendant une certaine période de temps (
décision de configuration SlaveDelay) réplique les incréments en amont, souvent utilisés dans les scénarios de restauration rapide.
        Arbiter : le nœud d'arbitrage, qui n'est utilisé que pour participer au vote électoral, ne transporte aucune donnée lui-même et ne sert que de rôle de vote. Par exemple, si vous déployez un jeu de réplicas avec 2 nœuds, 1 principal et 1 secondaire, si un nœud tombe en panne, le jeu de réplicas ne pourra pas fournir de services (le principal ne peut pas être sélectionné), vous pouvez alors ajouter un nœud Arbiter à le jeu de répliques, même si un nœud est en panne, le primaire peut toujours être sélectionné. Arbiter lui-même ne stocke pas de données et est un service très léger. Lorsque le nombre de membres du jeu de répliques est pair, il est préférable d'ajouter des nœuds ㇐ Arbiter pour améliorer la disponibilité du jeu de répliques.

 

Configurer les nœuds cachés

Dans de nombreux cas, définir des nœuds comme nœuds masqués est utilisé pour aider les membres retardés . Si nous avons seulement besoin
Pour éviter que ce nœud ne devienne le nœud maître, nous pouvons y parvenir via la priorité 0 membre .
cfg = rs.conf()
cfg.members[1].priority = 0
cfg.members[1].hidden = true
rs.reconfig(cfg)
Une fois définie, la priorité du nœud esclave sera changée en 0 pour l'empêcher d'être promu au nœud maître, et il est également invisible pour l'application. L'exécution de db.isMaster() sur d'autres nœuds n'affichera pas les nœuds cachés.
Configurer les nœuds de retard
Lorsque nous configurons un nœud retardé, le processus de réplication et l'oplog du nœud seront retardés. L'ensemble de données dans le nœud retardé sera postérieur à l'ensemble de données dans le nœud principal du jeu de réplicas. Par exemple, il est 09h52 maintenant, si le nœud de retard est retardé d'une heure, il n'y aura aucune opération après 08h52 dans l'ensemble de données du nœud de retard.
cfg = rs.conf()
cfg.members[1].priority = 0
cfg.members[1].hidden = true
#延迟1分钟
cfg.members[1].slaveDelay = 60
rs.reconfig(cfg)
Afficher le décalage de réplication
Si vous souhaitez afficher l'oplog du nœud actuel, vous pouvez utiliser la commande rs.printReplicationInfo()

Cela décrit clairement la taille de l'oplog, le temps de génération du premier oplog et du dernier oplog, et la longueur du journal du début à la fin fait référence à une fenêtre de réplication (différence de temps). Habituellement, lorsque la taille de l'oplog reste constante, plus l'opération d'écriture métier est fréquente, plus la fenêtre de réplication sera courte. Exécutez la commande rs.printSecondaryReplicationInfo() sur le nœud pour répertorier les délais de synchronisation de tous les membres du nœud de secours

Ajouter un nœud de vote

# 为仲裁节点创建数据目录,存放配置数据。该目录将不保存数据集
mkdir /data/arb
# 启动仲裁节点,指定数据目录和复制集名称
mongod ‐‐port 30000 ‐‐dbpath /data/arb ‐‐replSet rs0
# 进入mongo shell,添加仲裁节点到复制集
rs.addArb("ip:30000")
Supprimer un nœud de jeu de répliques
Utilisez rs.remove() pour supprimer des nœuds
rs.remove("ip:port")
Supprimer les nœuds par rs.reconfig()
cfg = rs.conf()
cfg.members.splice(2,1) #从2开始移除1个元素
rs.reconfig(cfg)
Modifier les nœuds du jeu de répliques
cfg = rs.conf()
cfg.members[0].host = "ip:port"
rs.reconfig(cfg)
Haute disponibilité de l'ensemble de réplicas
élection du jeu de répliques
L'élection du jeu de répliques de MongoDB est implémentée à l'aide de l'algorithme Raft ( https://raft.github.io/ ) La condition nécessaire pour une élection réussie est que la plupart des nœuds votants survivent . Dans l'implémentation spécifique, MongoDB ajoute quelques extensions au protocole raft, notamment :
Prend en charge le chaînageRéplication de chaîne autorisée, c'est-à-dire que le nœud de sauvegarde non seulement synchronise les données du nœud maître, mais sélectionne également un nœud le plus proche de lui-même (avec le plus petit délai de pulsation) pour répliquer les données .
Ajout de l'étape de pré-vote, à savoir preVote, qui est principalement utilisée pour éviter le problème de surtension de la valeur Term (terme) lorsque le réseau est partitionné
Prise en charge de la priorité de vote . Si le nœud de secours constate que sa priorité est supérieure à celle du nœud principal, il lancera activement un vote et tentera de devenir le nouveau nœud principal.
Un jeu de réplicas peut avoir jusqu'à 50 membres, mais seulement 7 membres votants. En effet, une fois que trop de membres participent au processus de réplication des données et de vote, cela entraînera davantage de problèmes de fiabilité.

Membres votants

la plupart

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

Lorsque le nombre de membres survivants dans le jeu de répliques est inférieur à la majorité, l'ensemble du jeu de répliques entier ne pourra pas élire un nœud principal et, pour le moment, ne pourra pas fournir de services d'écriture, et ces nœuds seront dans un état en lecture seule. . De plus, si vous souhaitez éviter le résultat d'un ticket à égalité, il est préférable d'utiliser un nombre impair de membres de nœud, par exemple 3 ou 5. Bien sûr, dans l'implémentation du jeu de réplicas MongoDB, une solution a été fournie pour le problème de ticket plat :
        Ajoutez une petite quantité d'écart de temps aléatoire au temporisateur d'élection, afin d'empêcher chaque nœud de lancer une élection en même temps et d'améliorer le taux de réussite.
        Utilisez le rôle d'arbitre, ce rôle n'effectue pas de réplication de données, n'entreprend pas de services de lecture et d'écriture et n'est utilisé que pour voter.
basculement automatique
Dans un scénario de basculement, nos préoccupations sont :
        Comment le nœud de secours perçoit-il que le nœud principal est en panne ?
        Comment réduire l'impact du basculement sur l'entreprise ?

        Un facteur qui affecte le mécanisme de détection est le battement de cœur. Une fois le jeu de réplicas établi, chaque nœud membre démarre un minuteur et continue d'envoyer des battements de cœur aux autres membres. Le paramètre impliqué ici est heartbeatIntervalMillis, qui est l'intervalle de battement de cœur, et la valeur par défaut la valeur est de 2s. Si le battement de cœur réussit, le battement de cœur continuera à être envoyé à une fréquence de 2 s ; si le battement de cœur échoue, le battement de cœur sera réessayé immédiatement jusqu'à ce que le battement de cœur reprenne avec succès.
        Un autre facteur important est la détection du délai d'expiration de l'élection, un échec de détection de battement de cœur ne déclenche pas immédiatement une réélection. réel
En plus de la pulsation, les nœuds membres démarreront également un temporisateur de détection de délai d'attente d'élection, qui est exécuté à un intervalle de 10 s par défaut, qui peut être spécifié par le paramètre electionsTimeoutMillis : si la réponse de pulsation est réussie, la dernière planification de electionsTimeout sera être annulé (garantie de ne pas déclencher d'élection) et lancer un nouveau cycle de planification de electionsTimeout. Si la réponse de pulsation échoue pendant une longue période, la tâche electionsTimeout est déclenchée, obligeant le nœud de secours à lancer une élection et à devenir le nouveau nœud principal. Dans l'implémentation de MongoDB, la période de détection du délai d'expiration des élections est légèrement plus longue que le paramètre electionsTimeoutMillis. Un décalage aléatoire sera ajouté à cette période, qui est d'environ 10 à 11,5 s. Cette conception consiste à échelonner le moment de l'élection active de plusieurs nœuds de secours et à améliorer le taux de réussite.
Par conséquent, les conditions suivantes doivent être remplies pour déclencher une élection dans la tâche electionsTimeout :
(1) Le nœud courant est le nœud de secours.
(2) Le nœud actuel a le pouvoir d'élection.
(3) Il n'y a toujours pas de succès dans la pulsation avec le nœud maître dans la période de détection.

 Évaluation de l'impact sur les entreprises

Dans le cas d'une commutation de nœud actif/en veille dans le jeu de réplicas, il y aura une courte période sans nœud actif et les opérations d'écriture métier ne peuvent pas être acceptées pour le moment. Si le basculement est dû à la défaillance du nœud principal, toutes les opérations de lecture et d'écriture sur le nœud expireront. Si vous utilisez le pilote de MongoDB 3.6 et supérieur, vous pouvez réduire l'impact en activant retryWrite.
# MongoDB Drivers 启用可重试写入
mongodb://localhost/?retryWrites=true
# mongo shell
mongo ‐‐retryWrites
Si le nœud maître est forcé de s'éteindre, l'ensemble du processus de basculement sera plus long et il peut être détecté et récupéré par d'autres nœuds après l'expiration du délai d'élection. Cette fenêtre de temps est généralement inférieure à 12 secondes. Cependant, dans la pratique, la prise en compte de la perte d'appels de service doit également inclure la surveillance du client ou des mongos et la perception du rôle de l'ensemble de répliques (la situation réelle peut prendre jusqu'à 30 secondes ou plus).
Pour les entreprises très importantes, il est recommandé de mettre en œuvre certaines stratégies de protection au niveau de l'entreprise, telles que la conception d'un mécanisme de nouvelle tentative.
Réflexion : comment redémarrer le jeu de répliques en douceur ?
Si vous souhaitez redémarrer le jeu de répliques sans perdre de données, une manière plus élégante de l'ouvrir devrait être la suivante :
1. Redémarrez tous les nœuds secondaires du jeu de réplicas un par un
2. Envoyez la commande rs.stepDown() au primaire et attendez que le primaire soit rétrogradé au secondaire
3. Redémarrez le primaire rétrogradé
Mécanisme de synchronisation des données du jeu de répliques
       Dans l'architecture du jeu de répliques, les données sont synchronisées entre le nœud principal et le nœud de secours via l'oplog . L'oplog est ici un ensemble fixe spécial. Lorsqu'une opération d'écriture sur le nœud principal est terminée, un enregistrement correspondant est écrit dans l'oplog. set.logs, tandis que le nœud de secours extrait en permanence de nouveaux journaux via cet oplog et les lit localement pour réaliser la synchronisation des données

 qu'est-ce qu'oplog

        MongoDB o plog est une collection sous la bibliothèque locale, qui est utilisée pour enregistrer les journaux incrémentiels générés par les opérations d'écriture (similaire à Binlog dans MySQL).
        Il s'agit d'une collection plafonnée (collection fixe) , c'est-à-dire que lorsque la valeur maximale configurée est dépassée, les données historiques les plus anciennes seront automatiquement supprimées.MongoDB a une optimisation spéciale pour la suppression de o plog afin d'améliorer l'efficacité de la suppression.
        Le nœud maître génère une nouvelle entrée o plog, et le nœud esclave maintient le même état que le nœud maître en copiant l'o plog et en l'appliquant ;
afficher le journal de bord
use local
db.oplog.rs.find().sort({$natural:‐1}).pretty()
local.system.replset : utilisé pour enregistrer les membres du jeu de répliques actuel.
local.startup_log : utilisé pour enregistrer les informations du journal de démarrage de la base de données locale.
local.replset.minvalid : utilisé pour enregistrer les informations de suivi du jeu de répliques, telles que les champs requis pour la synchronisation initiale.
ts : temps de fonctionnement, horodatage actuel + compteur, le compteur est réinitialisé toutes les secondes
v : informations sur la version d'oplog
op : type d'opération :
i : opération d'insertion
u : opération de mise à jour
d : opération de suppression
c : exécuter des commandes (telles que createDatabase, dropDatabase)
n : aucune opération, usage spécial
ns : l'ensemble sur lequel opérer
o : contenu de l'opération
o2 : condition de requête d'opération, seule l'opération de mise à jour contient ce champ
Le champ ts décrit l'horodatage généré par l'oplog, qui peut être appelé optime. Optime est la clé permettant au nœud de secours de réaliser une synchronisation incrémentielle des journaux . Il garantit que l'oplog est en ordre. Il se compose de deux parties :
        L'heure système actuelle, c'est-à-dire le nombre de secondes entre l'heure UNIX et l'heure actuelle, 32 bits.
        Minuterie entière, différentes valeurs de temps réinitialiseront le compteur, 32 bits
        Optime appartient au type Timestamp de BSON, qui est généralement utilisé en interne par MongoDB. Étant donné que l'oplog garantit l'ordre au niveau du nœud, le nœud de secours peut être extrait par polling , et la technologie de curseur tailable sera utilisée ici.
Chaque nœud de secours conserve son propre décalage, c'est-à-dire l'optimum du dernier journal extrait du nœud principal. Lors de la synchronisation, il utilise cet optimal pour interroger l'ensemble d'oplog du nœud principal. Afin d'éviter d'initier constamment de nouveaux liens de requête, vous pouvez bloquer le curseur après le démarrage de la première requête (en définissant le curseur comme tailable). De cette manière, tant que de nouveaux enregistrements sont générés dans l'oplog, le nœud de secours peut utiliser le même canal de requête pour obtenir ces données. Le curseur de queue ne peut être activé que lorsque la collection interrogée est une collection fixe.

La taille de la collection oplog
La taille de la collection oplog peut être définie par le paramètre replication.oplogSizeMB. Pour les systèmes 64 bits,
La valeur par défaut d'oplog est :
oplogSizeMB = min(磁盘可用空间*5%,50GB)
Pour la plupart des scénarios d'entreprise, il est difficile d'évaluer un oplogSize approprié au début, heureusement
MongoDB fournit la commande replSetResizeOplog après la version 4.0, qui peut modifier dynamiquement l'oplogSize
sans redémarrer le serveur.
# 将复制集成员的oplog大小修改为60g 指定大小必须大于990M
db.adminCommand({replSetResizeOplog: 1, size: 60000})
# 查看oplog大小
use local
db.oplog.rs.stats().maxSize
idempotence
Chaque enregistrement oplog décrit un changement atomique de données. Pour oplog, il doit être garanti qu'il est idempotent . C'est-à-dire que pour le même oplog, quel que soit le nombre d'opérations de lecture effectuées, l'état final des données restera inchangé. La valeur actuelle du champ x d'un certain document est 100, et l'utilisateur envoie un {$inc : {x : 1}} au primaire, qui sera converti en une opération {$set : {x : 101} lorsque enregistrement de l'oplog, afin d'assurer l'idempotence.
Le prix de l'idempotence
Pour l'opération d'éléments simples, la conversion de $inc en $set n'a aucun effet et le coût d'exécution est similaire, mais en ce qui concerne les opérations sur les éléments de tableau, la situation est différente.
test
db.coll.insert({_id:1,x:[1,2,3]})
Poussez 2 éléments à la fin du tableau, vérifiez l'oplog et constatez que l'opération $push a été convertie en une opération $set (définissez le tableau pour spécifier
l'élément à la position est une valeur)
rs0:PRIMARY> db.coll.update({_id: 1}, {$push: {x: { $each: [4, 5] }}})
 WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
 rs0:PRIMARY> db.coll.find()
 { "_id" : 1, "x" : [ 1, 2, 3, 4, 5 ] }
 rs0:PRIMARY> use local
 switched to db local
 rs0:PRIMARY> db.oplog.rs.find({ns:"test.coll"}).sort({$natural:‐1}).prett
()
 {
 "op" : "u",
 "ns" : "test.coll",
 "ui" : UUID("69c871e8‐8f99‐4734‐be5f‐c9c5d8565198"),
 "o" : {
 "$v" : 1,
 "$set" : {
 "x.3" : 4,
 "x.4" : 5
 }
 },
 "o2" : {
 "_id" : 1
 },
 "ts" : Timestamp(1646223051, 1),
 "t" : NumberLong(4),
 "v" : NumberLong(2),
 "wall" : ISODate("2022‐03‐02T12:10:51.882Z")
 }
Le coût de la conversion de $push en $set avec une position spécifique est similaire, mais regardons l'ajout de 2 éléments à la tête du tableau

On peut constater que lors de l'ajout d'éléments à la tête du tableau , l'opération $set dans l'oplog ne définit plus la valeur d'une certaine position dans le tableau (car fondamentalement, toutes les positions des éléments ont été ajustées), mais la finale résultat du tableau $set, c'est-à-dire que le contenu du tableau entier doit être écrit dans l'oplog. Lorsque l'opération push spécifie le paramètre $slice ou $sort, la méthode d'enregistrement oplog est la même et tout le contenu du tableau sera utilisé comme paramètre de $set. Les opérateurs de mise à jour tels que $pull et $addToSet sont similaires. Après la mise à jour du tableau, l'oplog sera converti dans le contenu final du tableau $set pour garantir l'idempotence.
L'écriture d'oplog est amplifiée, provoquant l'échec de la synchronisation - mise à jour du grand tableau
Lorsque le tableau est très volumineux, une petite mise à jour du tableau peut nécessiter l'enregistrement du contenu de l'ensemble du tableau dans l'oplog.J'ai rencontré un cas réel d'environnement de production où le document de l'utilisateur contenait un grand champ de tableau, 1000 La taille totale de les éléments font environ 64 Ko. Les éléments de ce tableau sont stockés dans l'ordre inverse du temps et les éléments nouvellement insérés seront placés au début du tableau.
($position : 0), puis conservez les 1000 premiers éléments du tableau ($slice : 1000).
À la suite du scénario ci-dessus, chaque fois qu'un nouvel élément est inséré dans le tableau sur le primaire (la demande est d'environ quelques centaines d'octets), le contenu du tableau entier doit être enregistré dans l'oplog. oplog et rejouez-le pendant la synchronisation, et le primaire synchronisera l'oplog sur le secondaire. Le trafic est des centaines de fois supérieur à celui du trafic réseau client-primaire, ce qui entraîne un trafic complet entre les cartes réseau principales et de secours. De plus, en raison de la grande quantité d'oplog, l'ancien contenu est rapidement supprimé, ce qui finit par empêcher le secondaire de rattraper son retard et passe à l'état RECOVERING. . Lorsque vous utilisez des tableaux dans des documents, vous devez prêter attention aux problèmes ci-dessus pour éviter que la mise à jour du tableau n'entraîne une amplification infinie de la surcharge de synchronisation. Lorsque vous utilisez des tableaux, essayez de faire attention à :
        1. Le nombre d'éléments dans le tableau ne doit pas être trop grand et la taille totale ne doit pas être trop grande
        2. Essayez d'éviter de mettre à jour le tableau
        3. Si vous devez mettre à jour, essayez de n'insérer des éléments qu'à la fin. Une logique complexe peut être considérée comme prise en charge au niveau de l'entreprise.

délai de réplication
Étant donné que la collection d'oplog a une taille fixe, l'oplog qui y est stocké peut être vidé par de nouveaux enregistrements à tout moment. Si la réplication du nœud de secours n'est pas assez rapide, il ne peut pas suivre le rythme du nœud principal, ce qui entraîne un problème de décalage de réplication . Une fois que le retard du nœud de secours est trop important, il y aura un risque de rupture de réplication à tout moment, ce qui signifie que l'optime (le dernier enregistrement de synchronisation) du nœud de secours a été dépassé par le nœud principal. nœud, de sorte que le nœud de secours ne pourra pas poursuivre la synchronisation des données.
Afin d'éviter autant que possible le risque de retard de réplication, nous pouvons prendre certaines mesures, telles que :
        Augmentez la taille de l'oplog et continuez à surveiller la fenêtre de réplication.
        Réduisez la vitesse d'écriture du nœud principal grâce à des moyens de mise à l'échelle.
        Optimisez le réseau entre les nœuds actifs et en veille.
        Évitez d'utiliser des tableaux trop volumineux pour les champs (peut provoquer un gonflement de l'oplog) .

restauration des données
        Étant donné que le délai de réplication est inévitable, cela signifie que les données entre les nœuds principal et secondaire ne peuvent pas être conservées en synchronisation absolue. Lorsque le nœud maître du jeu de réplication tombe en panne, le nœud de secours est réélu en tant que nouveau nœud maître. Ensuite, lorsque l'ancien nœud maître rejoint, certaines "données de journal modifiées" précédentes doivent être annulées pour s'assurer que l'ensemble de données est cohérent avec le nouveau nœud maître. Plus l'écart entre les jeux de réplication principal et de sauvegarde est grand, plus le risque de restaurations massives de données est élevé.
         Pour les données métier écrites, si elles ont été répliquées sur la plupart des nœuds du jeu de réplication, le risque d'annulation peut être évité. L'application peut assurer la persistance des données en définissant un niveau d'écriture plus élevé (writeConcern : majoritaire). Les données restaurées par l'ancien nœud maître seront écrites dans un répertoire de restauration séparé et les données pourront toujours être restaurées si nécessaire.
Lorsqu'une restauration se produit, MongoDB stocke les données de restauration au format BSON dans le dossier de restauration sous le chemin dbpath. Le format de dénomination du fichier BSON est le suivant : <database>.<collection>.<timestamp>.bson
mongorestore ‐‐host 192.168.30.130:27018 ‐‐db test ‐‐collection emp ‐u yanqiuxiang ‐p
yanqiuxiang
‐‐authenticationDatabase=admin rollback/emp_rollback.bson
Sélection de la source de synchronisation
MongoDB permet la réplication via le nœud de secours, ce qui se produit dans les situations suivantes :
Lorsque settings.chainingAllowed est activé, le nœud de secours sélectionne automatiquement le nœud le plus proche (avec le plus petit délai de commande ping) pour la synchronisation. L'option settings.chainingAllowed est activée par défaut, c'est-à-dire que par défaut, le nœud de secours ne choisit pas nécessairement le nœud principal pour la synchronisation. Cet effet secondaire augmentera le délai. Vous pouvez le désactiver par les opérations suivantes :
cfg = rs.config()
cfg.settings.chainingAllowed = false
rs.reconfig(cfg)
Utilisez la commande replSetSyncFrom pour modifier temporairement la source de synchronisation du nœud actuel. Par exemple, lors de l'initialisation de la synchronisation, faites pointer la source de synchronisation vers le nœud de secours pour réduire l'impact sur le nœud principal.
db.adminCommand( { replSetSyncFrom: "hostname:port" })

Je suppose que tu aimes

Origine blog.csdn.net/u011134399/article/details/131270334
conseillé
Classement