Tag

réplication

Browsing

Si vous utilisez les fonctions de réplication de MySQL ou MariaDB, il peut arriver que votre slave bloque sur une instruction qui devrait avoir un identifiant unique mais que le serveur tente d’insérer deux fois.

Créer un serveur High Availability : la réplication des bases de données photo

Et quand c’est le cas, la réplication des données prend fin donc c’est un problème à corriger rapidement si vous voulez que votre système haute disponibilité perdure et soit vraiment efficace en cas de coup dur.

Identification du problème

Je me suis rendu compte du problème lorsque j’ai ajouté de nouvelles bases à répliquer : j’ai relancé la procédure d’installation, relancé les serveurs, ajouté les nouvelles positions, démarré les slaves.

On regarde le status du slave :

MariaDB [(none)]> SHOW SLAVE STATUS\G

Résultat :

*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.134.23.164
                  Master_User: replicator
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mariadb-bin.000210
          Read_Master_Log_Pos: 2753885
               Relay_Log_File: mysqld-relay-bin.000002
                Relay_Log_Pos: 103794
        Relay_Master_Log_File: mariadb-bin.000210
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 1062
                   Last_Error: Error 'Duplicate entry '56-724' for key 'PRIMARY'' on query. Default database: 'frenchy'. Query: 'INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`) VALUES (56, 724)'
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1563407
              Relay_Log_Space: 1296874
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 1062
               Last_SQL_Error: Error 'Duplicate entry '56-724' for key 'PRIMARY'' on query. Default database: 'frenchy'. Query: 'INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`) VALUES (56, 724)'
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
               Master_SSL_Crl:
           Master_SSL_Crlpath:
                   Using_Gtid: No
                  Gtid_IO_Pos:
      Replicate_Do_Domain_Ids:
  Replicate_Ignore_Domain_Ids:
                Parallel_Mode: conservative
1 row in set (0.00 sec)

Comme on peut le constater, plusieurs choses ne tournent pas rond et empêchent la synchronisation des données entre nos deux serveurs :

Slave_SQL_Running: No
Last_SQL_Errno: 1062
Last_SQL_Error: Error 'Duplicate entry '56-724' for key 'PRIMARY'' on query. Default database: 'frenchy'. Query: 'INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`) VALUES (56, 724)'

Solution : un RESET sur le slave

En me documentant sur le problème, j’ai lu pas mal de choses sur le net. Certains préfèrent cacher l’erreur, au risque de perdre des données. D’autres préfèrent tout effacer pour recommencer la réplication.

Aucune de ces “solutions” ne me conviennent donc nous allons procéder autrement. Comme l’erreur n’apparaît que sur le serveur BACKUP et non sur le serveur principal, c’est sur lui que nous travaillerons.

Sur le serveur BACKUP, dans MariaDB, on arrête notre slave :

MariaDB [(none)]> STOP SLAVE;
Query OK, 0 rows affected (0.01 sec)

On flush les privilèges et donc les utilisateurs connectés :

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

On efface les fichiers logs de notre slave. C’est comme effacer une ardoise pour repartir sur des bases saines. Cela ne supprime aucune donnée – cf le manuel sur RESET :

MariaDB [(none)]> RESET SLAVE;
Query OK, 0 rows affected (0.00 sec)

Et on redémarre notre slave :

MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.00 sec)

On vérifie de nouveau le status de notre slave :

MariaDB [(none)]> SHOW SLAVE STATUS\G

Résultat :

*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.134.23.164
                  Master_User: replicator
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mariadb-bin.000196
          Read_Master_Log_Pos: 77900062
               Relay_Log_File: mysqld-relay-bin.000002
                Relay_Log_Pos: 6318821
        Relay_Master_Log_File: mariadb-bin.000192
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 6318531
              Relay_Log_Space: 344030331
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 833890
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
               Master_SSL_Crl:
           Master_SSL_Crlpath:
                   Using_Gtid: No
                  Gtid_IO_Pos:
      Replicate_Do_Domain_Ids:
  Replicate_Ignore_Domain_Ids:
                Parallel_Mode: conservative
1 row in set (0.00 sec)

Nous avons bien :

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

Et voilà, plus d’erreur et une réplication active dans les deux sens.

Après la réplication des bases de données et la réplication des fichiers, passons maintenant à la mise en place d’un load balancer avec keepalived et une IP flottante.

Voici le principe général de ce que nous cherchons à accomplir, avec une petite animation:

Serveur High Availability : créer un load balancer avec une IP flottante photo 1

Voici ce dont vous avez besoin pour ce tutoriel:

Installation et paramétrage de keepalived

Keepalived est une application de routage qui permet de fournir un moyen simple et robuste de mettre en place des solutions de load balancing et de haute disponibilité sur des systèmes Linux. Cela se passe au niveau de la couche 4 du modèle OSI :

Serveur High Availability : créer un load balancer avec une IP flottante photo

Concrètement, keepalived va vérifier toutes les quelques secondes que notre serveur de fichier est bien actif sur notre serveur MASTER. Si jamais le serveur est down, l’IP flottante sera assignée au serveur BACKUP. L’enregistrement DNS A du site doit pointer vers l’IP flottante. Cela permet de rediriger le trafic automatiquement et de manière transparente sur le serveur BACKUP.

Sur le serveur MASTER

1. On installe donc keepalived:

apt-get install keepalived

et on édite sa configuration init:

nano /etc/init/keepalived.conf

On y ajoute :

description "load-balancing and high-availability service"

start on runlevel [2345]
stop on runlevel [!2345]

respawn
exec /usr/local/sbin/keepalived --dont-fork

2. On obtient l’adresse IP privée du serveur:

curl http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address && echo

Résultat:

10.134.23.164

Sommaire de la série Créer un serveur High Availability (HA)

  1. Créer un serveur High Availability : la réplication des bases de données
  2. Créer un serveur High Availability : la réplication des fichiers
  3. Serveur High Availability : créer un load balancer avec une IP flottante

Nous avons vu il y a quelques jours comment répliquer nos bases de données à la volée d’un serveur à l’autre. Voyons aujourd’hui comment répliquer les fichiers en temps réel avec lsyncd.

Créer un serveur High Availability : la réplication des fichiers photo

Pour les besoins de ce tutoriel, vous avez besoin:

Mon serveur principal s’appelle MASTER. Le serveur de sauvegarde s’appelle BACKUP.

Copier tous les fichiers d’un serveur à l’autre avec rsync

rsync est le moyen le plus simple de copier tous les fichiers d’un répertoire sur votre serveur de sauvegarde.

Nous copions donc tous les fichiers qui se trouvent dans /var/www/html de notre serveur MASTER vers BACKUP :

rsync --progress -av --delete --stats --checksum --human-readable /var/www/html/* root@10.134.4.220:/var/www/html/

Cela permet d’avoir deux copies identiques très rapidement, surtout si vos deux VPS sont dans le même datacenter : vous pouvez alors utiliser l’IP interne du serveur – vitesse décuplée assurée (et cela ne compte pas dans la bande passante allouée).

La réplication des fichiers du site avec lsyncd

Je choisis d’utiliser lsyncd pour assurer la réplication des fichiers du site. C’est un petit service qui surveille le contenu d’un répertoire et qui fait un rsync toutes les 20 secondes vers votre autre VPS.

1. Sur le serveur MASTER, on installe lsyncd:

apt-get install lsyncd

2. Et on crée ses répertoires et son fichier de configuration :

mkdir /etc/lsyncd
mkdir /var/log/lsyncd
nano /etc/lsyncd/lsyncd.conf.lua

Sommaire de la série Créer un serveur High Availability (HA)

  1. Créer un serveur High Availability : la réplication des bases de données
  2. Créer un serveur High Availability : la réplication des fichiers
  3. Serveur High Availability : créer un load balancer avec une IP flottante

Ce tutoriel aborde la réplication des données d’un VPS ou serveur dédié : les bases de données seront répliquées d’un serveur principal (master) sur un autre serveur auxiliaire (backup).

Créer un serveur High Availability : la réplication des bases de données photo

En cas de défaillance du serveur principal, le serveur auxiliaire prendra le relais automatiquement.

Ce guide considère que vous avez :

  • deux VPS ou Droplets chez Digital Ocean dans le même datacenter;
  • une IP flottante qui peut être assignée à l’un ou l’autre des serveurs, à la demande;
  • le même système d’exploitation sur les deux serveurs, pour des raisons de compatibilité.

Créer une image du VPS principal pour le VPS de sauvegarde

Commençons par la base du système : le système d’exploitation (OS). Lorsque j’ai pris le projet en main, le site était déjà en production et tournait sur la dernière version d’Ubuntu Server, avec NginX, MariaDB et SSL activé.

On aurait pu tout réinstaller sur le nouveau VPS mais autant gagner du temps : Digital Ocean permet de faire une image du VPS existant et de l’installer sur un nouveau droplet. C’est quelques heures d’installation et de configuration d’économisées.

Voici les données de mes deux VPS :

MASTER

ipv4: 104.xxx.xxx.133
Private IP:  10.134.23.164

BACKUP

ipv4: 104.xxx.xxx.186
Private IP:  10.134.4.220

Floating IP

Floating IP:  138.xxx.xxx.177

Je masque les IP publiques puisque mes serveurs sont en production mais ces IP serviront pour le tuto : l’IP qui se termine en .133 est le Master, l’IP qui se termine en .186 est le Backup, et l’IP qui se termine en .177 est l’IP flottante.

Réplication de la base de données

Les deux serveurs LEMP sont maintenant identiques, même les fichiers et bases de données. Mais nous avons besoin d’avoir une base de données synchronisée en temps réel, dans les deux sens, master-master.

Si un serveur tombe, l’autre prend le relais. Lorsque le serveur Master revient à lui, le serveur Backup lui redonne les données SQL manquantes.

1. Configuration du serveur MASTER

On édite la configuration MariaDB:

nano /etc/mysql/my.cnf

On édite et remplace/ajoute :

# MATT - skyminds.net : MariaDB replication instructions.
# https://www.skyminds.net/?p=28739

# 1. bind-adress : replace 127.0.0.1 with Internal IP.
# bind-address          = 127.0.0.1
bind-address            = 10.134.23.164

# 2. enable log_bin
log_bin                 = /var/log/mysql/mariadb-bin
log_bin_index           = /var/log/mysql/mariadb-bin.index

# 3. add server-id AND binlog_do_db
# NOTE : server-id is a way to identify this server in MariaDB configs.
# NOTE : binlog_do_db contains the names of the databases to replicate
server-id               = 1
binlog_format=mixed
# first DB
binlog_do_db            = first_wpdb
# second DB
binlog_do_db            = second_wp

# /MATT

Nous allons maintenant lancer quelques commandes sur le serveur SQL:

mysql -u root -p

Sommaire de la série Créer un serveur High Availability (HA)

  1. Créer un serveur High Availability : la réplication des bases de données
  2. Créer un serveur High Availability : la réplication des fichiers
  3. Serveur High Availability : créer un load balancer avec une IP flottante
backup-safe

Aujourd’hui, j’aimerai aborder la réplication des fichiers.

Au sens général, il est prudent de toujours avoir une copie de sauvegarde : qui n’a jamais perdu un document précieux ou sur lequel il a passé des heures ?

Cela arrive à tout le monde un jour ou l’autre, dans des situations diverses et variées : un disque dur qui lâche, une clé USB qui s’égare, un service web qui ferme ses portes… nul n’est à l’abri d’une perte de données !

Le cas Rapidshare

C’est un secret de polichinelle aujourd’hui mais je vais quand même en parler : il paraît que l’on trouve des fichiers pas tout à fait légaux sur des hébergeurs de fichiers comme Rapidshare.

Selon mes sources (qui travaillent pour RS), le célèbre hébergeur sent la législation tourner en Europe et souhaiterait faire héberger ses serveurs dans un pays à la législation plus laxiste.

Le petit problème, c’est que des millions de fichiers sont hébergés chez eux et qu’ils ne peuvent pas les supprimer sans crier gare, sous peine de se voir boycotter par leurs usagers.