MariaDB Galera Cluster : la réplication multi maitres
Contents
Software version | 5.5 |
---|---|
Operating System | Debian 7 |
Website | MariaDB Website |
Last Update | 19/04/2014 |
Others | Galera 23.2.4(r147) |
1 Introduction
Si vous avez déjà fait de la réplication MySQL, vous avez que vous êtes limités à 2 nœuds maitre maximum. Que beaucoup d'actions se font à la main et qu'il est donc difficile d'avoir quelque chose de scalable et surtout accessible en écriture en simultané, du fait que par défaut les écritures soient synchrones.
Note: Si vous avez besoin de conseil ou de support sur MySQL/MariaDB/Galera, je vous recommande la société OceanDBA
Il existe donc un outil appelé Galera qui s'intègre à MariaDB ou MySQL (via recompilation dans les 2 cas) et qui permet de faire du multi maitres (3 nœuds minimum). Il existe plusieurs produits qui utilisent Galera :
- MariaDB Galera Cluster
- Percona Cluster
- MySQL Galera Cluster
Pour ceux qui se posent la question, c'est vraiment différent de MySQL Cluster qui sait scaler les écritures. Ici c'est multi threadé uniquement. Et contrairement à MHA qui est une solution asynchrone, Galera est synchrone.
Galera ne fonctionne que pour le moteur InnoDB et permet :
- Les réplications synchrones
- Des réplications multi maitres actifs
- Lecture/Écriture sur plusieurs nœuds simultané
- Détection automatique lorsqu'un nœud tombe
- Réintégration d'un nœud automatiquement
- Pas de lag au niveau des slaves
- Aucunes transactions perdues
- Latences clientes plus faible
Bien que cela semble parfait sur le papier, il y a quelques limitations :
- Supporte uniquement InnoDB
- Il faut qu'il y est des clés primaires sur toutes les tables
- DELETE ne fonctionne que sur les tables munies de clefs primaires
- LOCK/UNLOCK/GET_LOCK/RELEASE_LOCK ne fonctionne pas en multi maitre
- Les query logs ne peuvent être envoyés sur des tables, mais uniquement sur des fichiers
- Les transactions XA ne sont pas supportées
Pour vous aider à comprendre une architecture type :
Sachez également qu'un outil en ligne aide à la construction de ce genre d'infrastructures : Galera Configurator[2]
2 Installation
To install MariaDB, it's unfortunately not embedded in Debian, so we'll add a repository. First of all, install a python tool to get aptkey :
aptitude |
aptitude install python-software-properties |
Then let's add this repository (https://downloads.mariadb.org/mariadb/repositories/) :
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xcbcb082a1bb943db add-apt-repository 'deb http://mirrors.linsrv.net/mariadb/repo/10.0/debian wheezy main' |
We're now going to change apt pinning to prioritize MariaDB's repository :
/etc/apt/preferences.d/mariadb |
Package: * Pin: release o=MariaDB Pin-Priority: 1000 |
wget http://ftp.fr.debian.org/debian/pool/main/o/openssl/libssl0.9.8_0.9.8o-4squeeze14_amd64.deb dpkg -i libssl0.9.8_0.9.8o-4squeeze14_amd64.deb |
Maintenant, nous allons installer MariaDB et Galera :
aptitude |
aptitude update aptitude install mariadb-galera-server galera rsync openntpd |
Notes |
Le package rsync n'est pas obligatoire, mais nécessaire si vous allez utiliser cette méthode de transfert par la suite |
3 Configuration
3.1 MariaDB
Avant de commencer à toucher à la configuration, nous allons devoir supprimer des fichiers de logs sous peine que MariaDB ne démarre plus. Il va donc falloir couper le service mariadb :
service |
service mysql stop |
Puis nous mettons cette configuration MariaDB :
Nous allons maintenant supprimer les fichiers de logs car nous venons de toucher à leurs confs (sous peine de ne pas pouvoir démarrer d'instances) et pouvoir démarrer notre service MariaDB :
rm /var/lib/mysql/ib_logfile* service mysql start |
3.2 Galera
Voici la configuration à appliquer pour un cluster sur le même site :
- wsrep_cluster_name : le nom du cluster Galera. A utiliser, surtout si vous disposez de plusieurs cluster Galera dans le même subnet, afin d'éviter que certains noeuds entrent dans le mauvais cluster.
- wsrep_node_name : le nom de la machine sur laquelle se trouve ce fichier de configuration. Vous l'aurez compris, il faut a tout prix éviter les doublons (surtout pour le debug ;-))
- wsrep_node_address : adresse ip du noeud actuel (même avertissement que la ligne précédente)
- wsrep_cluster_address : liste des membres du cluster pouvant être maitre (séparé par des virgules).
- wsrep_provider_options : permet d'activer des options supplémentaires.
- gcache permet de stocker les données à transférer aux autres noeuds. Par défaut à 128M, il est conseillé d'augmenter cette valeur.[3]
- wsrep_retry_autocommit : permet de définir le nombre de tentatives une requête doit être réexécutée en cas de conflit.
- wsrep_sst_method : la méthode d'échange des données. Rsync est la plus rapide à l'heure actuelle.[4]
- wsrep_replication_myisam : permet d'activer la réplication des données MyISAM (pas de gestion des transactions...a éviter donc !)
- wsrep_sst_receive_address : permet de forcer l'utilisation d'une certaine adresse pour que les hôtes distants puissent se connecter (résous les problèmes de VIP)
- wsrep_notify_cmd : permet d’exécuter un script à chaque évènement de Galera (changement d'état d'un nœud)
- binlog_format : permet de définir le format des logs en mode ROW
- innodb_autoinc_lock_mode : modifie le comportement des verrous
- innodb_flush_log_at_trx_commit : optimisation des performances
Notes |
Adaptez les lignes wsrep_node_name et wsrep_cluster_address à vos machines respectives. |
La configuration ci dessus est applicable pour tous les nœuds, sauf pour le maitre (celui qui doit démarrer le premier). Celui ci doit avoir la configuration identique, à la seule différence de cette ligne :
/etc/mysql/conf.d/mariadb.cnf |
wsrep_cluster_address = 'gcomm://' |
WARNING |
Il est important qu'une seule machine ai la configuration 'gcomm://', car c'est l'initialisation du cluster |
3.3 Géo cluster
Il est possible de faire du Géo cluster, l'inconvénient c'est que lorsqu'il y a une coupure suppérieure aux timeouts indiqués, un des clusters va devoir se resynchroniser entièrement. Voici la ligne à configurer pour modifier ces timeouts :
Si vous utilisez l'option 'wsrep_sst_receive_address', il faudra rajouter un paramètre sur cette ligne (ist.recv_addr) et mettre la même ip que l'option 'wsrep_sst_receive_address' :
3.4 Méthodes de réplications
Il existe plusieurs solutions pour les transferts de données entre noeuds. Dans l'exemple plus haut, nous avons utilisé rsync. Lorsqu'une machine demande à un donor (une autre machine) de recevoir les données, les transactions sont bloqués pour le donneur durant la période d'échange de données avec le receveur !!!
WARNING |
Si vous utilisez un load balancer, il faudra sortir le noeud donneur pendant cette période là |
Ce blocage peut être toutefois limité en utilisant la méthode xtrabackup.
3.4.1 mysqldump
SST (State Snapshot Transfert) va permettre de faire des échanges complets (uniquement, pas d'incrémentale). Il faut donc créer un utilisateur sur toutes les machines :
mysql |
grant all on *.* to 'sst_user'@'%' identified by 'sst_password'; |
Puis modifier la configuration pour que le user et le password concordent :
/etc/mysql/conf.d/mariadb.cnf |
[...] wsrep_sst_auth = 'sst_user:sst_password' [...] |
Du coup, lorsque l'on intègre un nouveau noeud, on peut constater qu'un nœud est passé en donneur :
On voit également que la valeur du wsrep_local_state change à 4 pour que le process soit terminé.[5]
3.4.2 Rsync
C'est une méthode très efficace ! L'inconvénient majeur est qu'elle ne permet pas de faire des transferts à chaud. Voici comment configurer le SST :
/etc/mysql/conf.d/mariadb.cnf |
[...] wsrep_sst_method = rsync [...] |
Il faut que les données ne soient plus accédées par MariaDB pour que cela fonctionne correctement. Un autre prérequis est la présence d'rsync sur les serveurs.
3.4.3 XtraBackup
XtraBackup est la meilleure méthode aujourd'hui. Elle permet de faire des transferts en minimisant le temps de lock qui n'est que de quelques secondes. Pour que l'on puisse utiliser cette méthode, il faut installer XtraBackup.
Pour l'installer sur une Debian, c'est très simple, nous allons rajouter son repository :
gpg |
apt-key adv --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A |
Créez ce fichier pour ajouter le repository :
/etc/apt/sources.list.d/percona.list |
deb http://repo.percona.com/apt VERSION main deb-src http://repo.percona.com/apt VERSION main |
On update et on installe :
aptitude |
aptitude update aptitude install xtrabackup |
Puis on peut configurer nos noeuds pour qu'ils utilisent cette méthode :
/etc/mysql/conf.d/mariadb.cnf |
[...] wsrep_sst_method = xtrabackup [...] |
3.4.4 Spécifier un donor
Pour ce qui est de la réplication, si vous souhaitez à tout moment dédier une machine en donor (et éventuellement pour les backups) depuis un serveur :
mysql |
SET global wsrep_sst_donor=<node3> |
Ceci résous la problématique du load balancer cité plus haut et évite les blocages durant un backup.
Sinon vous pouvez le spécifier directement pour l'intégration d'un noeud :
mysqld |
mysqld --wsrep_cluster_address='gcomm://<node1>' --wsrep_sst_donor='<node1>' |
Notes |
Si vous démarrez 2 fois de suite MariaDB sans lancer au moins une fois une synchro Galera, la 2ème fois, il fera une synchro complète |
4 Utilisation
Avant de passer à l'utilisation, il faut comprendre le principe. Lorsque nous allons démarrer nos instances MariaDB, nous allons nous retrouver dans ce cas de configuration (je n'ai volontairement pas fait toutes les flèches de communication pour éviter que ça devienne trop fouillis, mais tous les nodes discutent entre eux) :
- Le node 1 initialise le cluster avec la valeur du gcomm vide.
- Les autres nodes se connectent sur le node 1 et échangent leurs données pour avoir le même niveau de données partout
4.1 Création du cluster
Mettez vous sur le node 1 afin de créer le cluster. Nous allons l'allumer avec une adresse de cluster vide, qui va indiquer sa création :
mysqld |
service mysql start --wsrep_cluster_address='gcomm://' ou mysqld --wsrep_cluster_address='gcomm://' |
4.2 Ajouter des noeuds dans le cluster
Pour joindre des nodes au cluster qui vient d'être créer, c'est simple :
mysqld |
service mysql start --wsrep_cluster_address='gcomm://<ip_du_node_1>' ou mysqld --wsrep_cluster_address='gcomm://<ip_du_node_1>' |
Mettez donc l'IP du node 1 pour se connecter à lui. Vous pouvez également simplement démarrer le service MariaDB, car nous avons une configuration qui est fonctionnelle :
service mysql start |
Si vous n'arrivez pas à joindre le master, lancez cette commande sur dans mysql sur le master pour être sur qu'il est bien démarré :
mysql |
SET global wsrep_cluster_address='gcomm://' |
Notes |
Vous pouvez utilisez les IP ou des noms DNS |
4.3 Vérifier l'état du cluster
Pour vérifier l'état du cluster, voici la commande à exécuter dans MariaDB :
Ici je n'ai que mon serveur principale qui tourne. Aucun autre node n'a encore joint le cluster. Mais lorsque j'en ajoute :
Je vois bien ici mes 4 noeuds master :-)
5 Garbd (quorum)
Afin d'éviter les split brains (inconsistances cluster), il est conseillé d'utiliser un outil fournit avec le cluster Galera qui agira comme un quorum cluster, surtout si vous êtes en mode 2 noeuds (et c'est généralement là le principale avantage). Voici un cas d'utilisation[6] :
,---------. | garbd | `---------' ,---------. | ,---------. | clients | | | clients | `---------' | `---------' \ | / \ ,---. / (' `) ( WAN ) (. ,) / `---' \ / \ ,---------. ,---------. | node1 | | node2 | | node3 | | node4 | `---------' `---------' Data Center 1 Data Center 2
Il faudra alors utiliser le service garbd. Il est installé de base, mais n'est tout simplement pas activé. Pour le configurer, nous allons éditer sa configuration :
Adaptez le GALERA_NODES avec la liste de tous vos nodes et le GALERA_GROUP avec le nom du cluster Galera. Il ne reste plus qu'à l'activer au démarrage de la machine et démarrer le service :
update-rc.d -f garb defaults service garb start |
Maintenant, sur un de vos noeuds, vous pourrez voir qu'il y a un nouveau node, qui n'est en fait que le quorum :
6 Sauvegardes et restaurations
Pour la sauvegarde, il existe plusieurs méthodes et Xtrabackup est encore une fois l'une des favoris.
Notes |
Tout comme lorsqu'un nouveau nœud s'ajoute au cluster et bloque les transactions du donor, c'est pareil pour les backups, mais uniquement pour MyISAM ! |
Si vous utilisez que de l'InnoDB et utilisez Xtrabackup, il n'y aura pas de locks de transactions et donc pas de nœud spécial à prévoir pour les backups !
6.1 Installation
Pour l'installer sur une Debian, c'est très simple, nous allons rajouter son repository :
gpg |
apt-key adv --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A |
Créez ce fichier pour ajouter le repository :
/etc/apt/sources.list.d/percona.list |
deb http://repo.percona.com/apt VERSION main deb-src http://repo.percona.com/apt VERSION main |
On update et on installe :
aptitude |
aptitude update aptitude install xtrabackup |
6.2 Utilisation
6.2.1 Sauvegarde
Pour sauvegarder un Galera et permettre une sauvegarde incrémentielle en bloquant le nœud qui va effectuer les sauvegardes, uniquement quelques secondes :
innobackupex |
innobackupex --galera-info --user=xxxxx --password=xxxx <repertoire_ou_stocker_le_backup> |
L'option 'galera-info' permet de ne pas avoir de problèmes durant la demande d'uuid (qui retournera tout le temps 0). Si on ne spécifie pas cette option, on ne pourra pas faire de restaurations incrémentiels.
Notes |
Pour les bases de données ne contenant que des tables uniquement en InnoDB, il est possible de ne pas du tout avoir de blocage lors du lock en ajoutant l'option '--no-lock' |
6.2.2 Restauration
Durant la restauration, un des nœuds aura des transactions bloquées après la restauration d'Xtrabackup, le temps d'effectuer le différentiel. Pour restaurer on copie les fichiers de sauvegarde dans le répertoire de MariaDB :
cp -Rf <repertoire_du_backup> /var/lib/mysql/ chown -Rf mysql. /var/lib/mysql/ |
On peut spécifier le donor (optionnel), puis on va vérifier la position du backup :
cat |
> cat <repertoire_du_backup>/xtrabackup_galera_info cfa9b8f1-f37b-11e2-0800-b37f8ac5092c:1 |
Et on intègre le nœud au cluster en lui spécifiant la position pour éviter qu'il récupère une sauvegarde complète :
7 Récupération et maintenance
7.1 Méthode automatique
Il n'y a pas à se soucier de la réplication si un nœud tombe autre que le master (node1). Une fois réparé et allumé, il se reconnectera automatiquement sur le node 1 et rattrapera son retard. Par contre, en cas de problème sur le noeud 1 :
Les autres nodes continueront à communiquer entre eux et attendront le maitre revienne. Une fois le maitre rallumé, il va falloir lui indiquer un autre noeud sur lequel il devra se connecter pour continuer la synchro :
Que ce soit pour forcer une reconnexion ou si vous voulez effectuer une maintenance sur le nœud master, il est conseillé de rediriger les autres serveurs vers un autre master pour éviter les coupures :
mysql |
SET GLOBAL wsrep_cluster_address='gcomm://10.0.0.2'; |
Vous pouvez ensuite vérifier le noeud maitre sur vos instances MariaDB :
J'ai également testé de couper violemment n'importe quel node et le rallumer, une fois intégré dans le cluster, il récupère bien toutes le différentiel d'informations. J'ai poussé les tests et n'ai eu aucuns problèmes de corruptions. Les seuls problèmes que j'ai pu avoir étaient le démarrage de MariaDB et les problèmes de lock comme expliqué dans la #FAQ.
7.2 Méthode manuelle
Il est possible de mettre à jour un noeud depuis un delta entre une version à jour et celle d'un autre en retard. Pour cela, il faut regarder la version dans laquelle se trouve un des noeuds à jour :
On peut voir ici le numéro d'uuid, ainsi que la position du dernier commit (wsrep_last_committed).
WARNING |
La commande suivant est à utiliser uniquement sur serveur éteint sous peine de perdre les données sur celui ci !!! |
Sur serveur éteint, il est possible de récupérer la position du dernier commit :
Puis on peut relancer le delta depuis ce dernier commit :
mysqld |
mysqld --wsrep_start_position=<uuid>:<position> soit mysqld --wsrep_start_position=3e10ea72-f2b9-11e2-0800-4b821a7d26d5:4 |
La delta est alors effectué et le serveur en question est maintenant à la position 6.
7.3 Forcer un noeud à se resynchroniser
Si vous ne savez vraiment pas ce qu'un nœud a et que vous voulez le resynchroniser complètement car vous n'êtes pas sur des données qu'il contient, il suffit de supprimer le contenu de mariadb et de le relancer :
service mysql stop rm -Rf /var/lib/mysql/* service mysql start |
Toutes les données vont alors se resynchroniser.
WARNING |
Ceci peut durer un certain temps si votre base de données est grosses ou que la bande passante entre les nœuds est faible |
7.4 Split brain
Lorsque l'on a un ou plusieurs nœuds en état de split brain, il est possible de continuer d'utiliser le cluster et de discard tous les changements des autres noeuds down pour qu'ils refassent une synchro complète au démarrage de ceux ci. Sur un serveur en 'primary' :
mysqld |
SET global wsrep_provider_options = 'pc.bootstrap=1'; SET global wsrep_provider_options = 'pc.ignore_quorum=0'; |
- pc.bootstrap : prend la main sur les autres noeuds du cluster et indique que c'est lui le master
- pc.ignore_quorum : autorise à spliter les noeuds et avoir un split brain
Relancez ensuite vos autres serveurs pour qu'ils se synchronisent.
WARNING |
Une fois que le cluster est rétablit, il faut ABSOLUMENT repasser ces variables à False pour éviter des split brains à l'avenir sans pouvoir revenir en arrière !!! |
8 FAQ
8.1 Un de mes services MariaDB refuse de démarrer après arrêt de celui ci
Il peut arriver que lorsque l'on éteint un service MariaDB, les fichiers de locks se libèrent mal et que le service rsync tourne encore. Pour mettre tout au propre (sans éviter de redémarrer complètement la machine), voici les opérations à suivre :
1. On s'assure que MariaDB ne fonctionne plus :
service mysql stop ps aux | grep mysql |
2. Si ça tourne encore, on kill le processus !
3. On vérifie que le process rsync ne tourne plus et on le kill si c'est le cas
4. On supprime le fichiers de lock :
rm |
rm -f /var/run/mysqld/mysqld.sock |
5. On vérifie que le dossier pour stocker le pid existe, sinon on le créer :
if [ ! -d /var/run/mysqld ] ; then mkdir /var/run/mysqld ; chown mysql. /var/run/mysqld ; fi |
6. Vous pouvez maintenant démarrer le service, ça devrait fonctionner :
service mysql start |
Sinon regardez les logs (/var/log/syslog)
8.2 /dev/stderr: Permission denied
Si vous avez ce problèmes c'est du à un bug de Galera qui redirige mal sa sortie d'erreur :
/usr//bin/wsrep_sst_common: line 94: /dev/stderr: Permission denied
Pour corriger le problème, il suffit de mettre les bons droits sur la sortir d'erreurs :
chmod 777 /proc/self/fd/2 |
9 References
- ^ http://www.codership.com/wiki/doku.php?id=galera_deployment
- ^ http://www.severalnines.com/galera-configurator/
- ^ http://www.severalnines.com/blog/understanding-gcache-galera
- ^ http://www.codership.com/wiki/doku.php?id=sst_mysql
- ^ http://www.codership.com/wiki/doku.php?id=galera_node_fsm
- ^ http://www.sebastien-han.fr/blog/2012/04/01/mysql-multi-master-replication-with-galera/