La réplication MySQL est-elle affectée par une interconnexion à haute latence?


11

Nous avons une configuration MySQL maître et esclave vanilla qui réside dans différents centres de données, et un autre esclave dans le même centre de données que le maître.

La bande passante entre le centre de données est assez élevée (dans les tests de performances réseau que nous avons effectués, nous pouvons atteindre 15 Mo / seconde), mais la latence existe, elle est d'environ 28 ms. Ce n'est pas élevé du tout, mais il est beaucoup plus élevé que la latence inférieure à la seconde dans le même centre de données.

Parfois, nous rencontrons de graves retards (2000 secondes et plus) avec l'esclave à supprimer, tandis que l'esclave local reste à jour. Lorsque vous regardez l'esclave distant en retard, le thread SQL passe généralement le temps à attendre que le thread IO mette à jour le journal de relais. Le maître affiche "en attente de filet" ou quelque chose du genre en même temps.

Cela signifie donc que c'est un réseau, mais nous avons encore de la bande passante libre au moment où cela se produit.

Ma question est : la latence entre les centres de données peut-elle affecter les performances de la réplication? Le thread io esclave diffuse-t-il simplement les événements jusqu'à ce que le maître arrête de les envoyer, ou met-il en commun le maître d'une manière ou d'une autre entre les événements?


2000 secondes? Donc, un décalage de 33 minutes?
Richard

Oui ... Ça monte et descend tout au long de la journée.
shlomoid

2
+1 parce que j'aime ce type de questions sur ce site. Veuillez faire passer le mot pour que d'autres personnes viennent sur ce site avec des questions de cette nature !!!
RolandoMySQLDBA

Réponses:


7

La réponse directe à votre question est Oui, mais cela dépend de la version de MySQL que vous utilisez. Avant MySQL 5.5, la réplication fonctionnait comme suit:

  • Le maître exécute SQL
  • Master Records SQL Event dans ses journaux binaires
  • L'esclave lit l'événement SQL à partir des journaux binaires principaux
  • L'esclave stocke l'événement SQL dans ses journaux de relais via le thread d'E / S
  • L'esclave lit le prochain événement SQL à partir du journal de relais via le thread SQL
  • Esclave exécute SQL
  • Slave reconnaît maître de l'exécution complète de l'événement SQL

Depuis MySQL 5.5, en utilisant la réplication semi-synchrone , la réplication fonctionnerait désormais comme suit:

  • Le maître exécute SQL
  • Master Records SQL Event dans ses journaux binaires
  • L'esclave lit l'événement SQL à partir des journaux binaires principaux
  • L'esclave reconnaît le maître de la réception de l'événement SQL
  • L'esclave stocke l'événement SQL dans ses journaux de relais via le thread d'E / S
  • L'esclave lit le prochain événement SQL à partir du journal de relais via le thread SQL
  • Esclave exécute SQL
  • Slave reconnaît maître de l'exécution complète de l'événement SQL

Ce nouveau paradigme permettra à un esclave d'être plus synchronisé avec son maître.

Nonobstant, la latence au sein du réseau pourrait entraver la réplication MySQL Semisync au point de revenir à la réplication asynchrone à l'ancienne. Pourquoi ? Si un délai d'attente se produit sans qu'aucun esclave n'ait acquitté la transaction, le maître revient à la réplication asynchrone. Lorsqu'au moins un esclave semi-synchrone rattrape, le maître revient à la réplication semi-synchrone.

MISE À JOUR 2011-08-08 14:22 EDT

La configuration de la réplication semi-synchrone MySQL 5.5 est simple

Étape 1) Ajoutez ces quatre (4) lignes à /etc/my.cnf

[mysqld]
plugin-dir=/usr/lib64/mysql/plugin
#rpl_semi_sync_master_enabled
#rpl_semi_sync_master_timeout=5000
#rpl_semi_sync_slave_enabled

Étape 2) Redémarrez MySQL

service mysql restart

Étape 3) Exécutez ces commandes dans le client MySQL

INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
INSTALL PLUGIN rpl_semi_sync_slave  SONAME 'semisync_slave.so';

Étape 4) Décommentez les trois options rpm_semi_sync après l'option plugin-dir

[mysqld]
plugin-dir=/usr/lib64/mysql/plugin
rpl_semi_sync_master_enabled
rpl_semi_sync_master_timeout=5000
rpl_semi_sync_slave_enabled

Étape 5) Redémarrez MySQL

service mysql restart

Terminé !!! Maintenant, configurez la réplication MySQL comme d'habitude.


Je ne suis pas sûr de la dernière étape de la réplication asynchrone - je ne pense pas que le maître sache jusqu'où chaque esclave est arrivé. Ils peuvent demander n'importe quelle partie du journal binaire qu'ils veulent, autant que je sache - avez-vous une référence pour cela?
shlomoid

En outre, nous utilisons la réplication asynchrone par défaut dans MySQL, pas le type asynchrone - qui doit être activé exprès en installant des plugins et autres. Ce que j'essaie de comprendre, c'est si les événements sont canalisés dans le style net-cat vers l'esclave à partir de la position de départ dans le journal, ou s'il y a des échanges entre le maître et l'esclave pour chaque événement, qui pourrait souffrir d'une telle latence.
shlomoid

Par tous les moyens, je recommande fortement d'utiliser MySQL 5.5 pour profiter de cette nouvelle forme de réplication MySQL ainsi que des améliorations d'InnoDB.
RolandoMySQLDBA

1
Oui, bien sûr, nous utilisons MySQL 5.5, mais ce n'est pas le type de réplication par défaut. Vous devez passer par toute une procédure de configuration, installer des plugins et autres, pour le faire fonctionner de manière semi-synchrone.
shlomoid

2

J'aime vraiment la façon dont Rolando a décrit la séquence d'opérations qu'une réplication effectue. Cependant, je pense qu'il serait plus clair si nous ajoutons un autre composant - client.

Avec le client, la séquence d'opérations pour la réplication asynchrone peut être la suivante:

  1. Le client envoie au maître la requête SQL (par exemple, insérer) à l'aide de transactions

  2. Le maître exécute la transaction. En cas de succès, l'enregistrement est stocké sur le disque, mais la transaction n'est pas encore validée.

  3. Le maître enregistre l'événement d'insertion dans le journal binaire principal Si le maître n'a pas pu le stocker dans le journal binaire, la transaction a été annulée.

  4. Le client reçoit une réponse du maître (succès ou annulation).

  5. En cas de réussite de la transaction, le thread de vidage sur le maître lit l'événement dans le journal binaire et l'envoie au thread d'E / S esclave.

  6. Le thread d'E / S esclave reçoit l'événement et l'écrit à la fin du fichier journal de relais.

  7. Une fois que l'événement est entré dans le journal de relais, le thread SQL esclave exécute
    l'événement pour appliquer les modifications à la base de données sur l'esclave.

Dans ce scénario, le maître ne se soucie pas de l'esclave et le client sait seulement que quelque chose ne va pas sur l'esclave en exécutant manuellement la commande "SHOW SLAVE STATUS".

Dans le cas d'une réplication semi-synchrone, la séquence d'opérations pourrait être la suivante:

  1. Le client envoie au maître la requête SQL (par exemple, insérer) à l'aide de transactions.

  2. Le maître exécute la transaction. En cas de succès, l'enregistrement est stocké sur le disque, mais la transaction n'est pas validée.

  3. Le maître enregistre l'événement d'insertion dans le journal binaire principal Si le maître n'a pas pu le stocker dans le journal binaire, la transaction est annulée et le client reçoit la réponse uniquement en cas de restauration.

  4. En raison du succès de la transaction sur le maître, le thread de vidage sur le maître lit l'événement dans le journal binaire et l'envoie au thread d'E / S esclave.

  5. Le thread d'E / S esclave reçoit l'événement et l'écrit à la fin du fichier journal de relais.

  6. L'esclave reconnaît le maître de l'enregistrement de l'événement dans le fichier journal du relais.

  7. Le maître valide la transaction d'insertion.

  8. Le client reçoit la réponse du maître (succès).

  9. Une fois que l'événement est entré dans le journal de relais, le thread SQL esclave exécute
    l'événement. Le maître et le client ne savent pas si l'exécution a réussi ou non.

La réplication semi-synchrone a résolu un cas important lorsque l'esclave ou le réseau est mort et que le maître a continué de procéder. Ensuite, le maître meurt et vous souhaitez redémarrer l'ancien esclave en tant que nouveau maître simplement parce que vous avez corrigé ce nœud.

Vous avez donc commencé ce nœud en tant que nouveau maître, vous avez corrigé l'ancien maître et maintenant vous voulez l'utiliser comme esclave. Ce nœud contient toujours les données, mais si le nouvel esclave commence à la position où le nouveau maître a commencé, il y aura des enregistrements en double.

Si la période d'attente est infinie, la position du journal binaire maître sera toujours synchronisée avec la position du journal du relais esclave en supposant que toutes les requêtes sur l'esclave ont réussi. Dans quelle mesure cette hypothèse est-elle réaliste?

Je pense que c'est très réaliste. L'un des cas les plus courants d'échec de requête esclave est "enregistrement en double". Où le dossier en double est-il parvenu à l'esclave si le maître ne l'avait pas? Cela venait d'une mauvaise position donnée à l'esclave pour commencer à se répliquer. La position de réplication de départ comprenait l'enregistrement déjà répliqué. En cas de réplication semi-synchrone, cette situation ne se produira pas.

Jacob Nikom


1

Qualifier : je ne suis pas un utilisateur MySQL, donc surtout, ce ne sont que mes recherches sur Internet.

Comme je suis sûr que vous le savez, la plus grande limitation de la réplication MySQL est qu'il s'agit d'un seul thread. Ainsi, alors que le thread est occupé à envoyer des données à l'esclave interne, il ne pourra pas envoyer de données à l'esclave distant. C'est par ici .


Par ici :

Une chose que vous devez vous assurer est de réduire le temps de transaction. Cela permet à votre thread de réplication de rattraper ce qui se passe dans la base de données. Vous souhaitez que vos transactions soient aussi courtes que possible.

Une façon de procéder consiste à couper les requêtes; limiter les lignes modifiées par UPDATE ou DELETE via l'utilisation de clauses WHERE. Si vous collez cela dans une boucle, vous pouvez parcourir la liste, en commençant et en validant la transaction à chaque fois. (METTRE À JOUR / SUPPRIMER le premier tiers, le deuxième tiers, puis le dernier tiers chacun dans sa propre transaction.) Personnellement, je déconseille fortement de le faire parce que vous vous ouvrez à la possibilité que les données du tableau changent entre les transactions. Mais, c'est une possibilité d'améliorer ces performances si vous êtes sûr que personne d'autre ne joue avec la table (et ne le fera jamais) .

Une autre possibilité consiste à ne pas répliquer ces transactions de longue durée, mais plutôt à les exécuter sur le maître (qui se réplique sur l'esclave local), puis à les exécuter séparément sur l'esclave distant. Cela libérerait le fil de réplication afin qu'il ne s'embourbe pas jusqu'à 30 minutes.


Par ici :

Une dernière possibilité serait de régler la taille de vos tampons TCP. L'objectif est de réduire le nombre de communications que vous établissez entre le maître et l'esclave. Cela pourrait aider à réduire la latence.

Personnellement, j'essaierais cela si tout le reste échoue. Je soupçonne que le problème est davantage causé par le système de réplication à thread unique plutôt que par une latence du réseau. Les réseaux expireraient normalement bien avant 30 minutes. (30 minutes?!)


Les signets Delicious de JHammerb ont plusieurs liens pour la réplication mysql que vous pouvez également consulter.

J'espère que ça aide.


1
Vous obtenez un +1 pour avoir mentionné comment la réplication MySQL est monothread, mais je dois qualifier votre déclaration comme suit: la réplication MySQL est à double thread utilisant un thread d'E / S pour télécharger les événements SQL du maître vers l'esclave et un thread SQL pour le traitement les événements SQL localement sur l'esclave. Pourtant, la transmission des événements SQL est monothread, ce qui est contextuellement correct pour cette question.
RolandoMySQLDBA

2
BTW Veuillez ne pas utiliser LIMIT avec les instructions UPDATE et DELETE car l'ordre des lignes mises à jour ou supprimées peut ne pas être le même sur l'esclave que sur le maître. Si tel est le cas, des messages d'avertissement à ce sujet apparaissent quelque chose comme "Statement Not BinLog-Safe" dans le journal des erreurs.
RolandoMySQLDBA

Ooh, bon point de ne pas utiliser LIMIT avec UPDATE et DELETE. Je vais modifier ma réponse pour supprimer cela.
Richard
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.