lindev : administration linux , développement php

Aller au contenu | Aller au menu | Aller à la recherche

11 déc. 2009

Réplication mysql

MIse en place

Refresh.png Après avoir écrit cet article je me suis aperçu que le procédé ne fonctionne pas parfaitement .... notamment si des données existent déjà sur le serveur maître .

Je vous présente donc ma façon de faire , afin de mettre en place une réplication avec un serveur déjà en production .

Note : Pas de différence entre le moteur des tables MyIsam , InnoDb .

Utilisateur de replication

Je vais créer sur le maître un utilisateur , qui aura les droits pour effectuer sa réplication .

mysql -uroot -p*******
CREATE USER 'slave_user'@'%' IDENTIFIED BY  'motdepasse';
GRANT REPLICATION SLAVE ON *.* TO slave_user@'%' IDENTIFIED BY 'motdepasse';
FLUSH PRIVILEGES;

Faits attention à ce qu'il n'y ai pas plusieurs utilisateurs du même nom .

Fichiers de conf

Il nous faut faire quelques modifications dans les fichiers de conf des serveurs maître est esclave ... pas de panique , quivez le guide .

Maître

vim /etc/mysql/my.cnf

Dans la section mysqld Il faut juste vérifier à ce que les paramètres suivants soient dé-commentés.

server-id = 1
log_bin   = /var/log/mysql/mysql-bin.log

Server-id se doit d'être unique , sur l'esclave , nous mettrons donc 2
Par contre , commentez le paramètre suivant:

#bind-adress = 127.0.0.1 

Sans quoi les connexions extérieures n'aboutirons pas .

Esclave

vim /etc/mysql/my.cnf

Dans la section mysqld Il faut juste vérifier à ce que les paramètres suivants soient dé-commentés et configurés.

server-id = 2
master-host=ipservmaitre
master-user=slave_user
master-password=******
master-port=3306


Par contre , commentez le paramètre suivant:

#bind-adress = 127.0.0.1 

Sans quoi les connexions extérieures n'aboutirons pas .




Ensuite , Commençons par couper les services qui écrivent sur les bases

Sur le maître et l'esclave :

Dans mon cas , je n'ai eu qu'à couper apache et cron

/etc/init.d/apache2 stop
/etc/init.d/cron stop

Sur le maître

Le principe est le suivant :

  1. RESET des logs binaires
  2. Visualisation de la position
  3. Dump
  4. Envoie du dump ver l'esclave

1 RESET des logs 2:Position

Connectons nous à mysql:

mysql -uroot -p*******
RESET MASTER;
SHOW MASTER STATUS;
exit

Ce qui doit donner :

showmaster.png

Il vous faut noter précieusement le nom du fichier binaire , et la position ici par exemple :

  • mysql-bin.000001
  • 13860

3 Dump des bases du maître

Dans mon cas , je vais repliquer l'ensemble des bases de mon serveur maître, j'utilise donc la commande suivante :

mysqldump -uroot -p******* --databases databaseA databaseB databaseC >/root/dump.sql

Note: je n'ai pas utilisé --all-databases , pour la simple raison , que cela produit un conflit avec la base information_schema et mysql , j'ai donc sélectionné toutes mes bases .

4: Envoie du dump vers le serveur esclave

Bon , juste pour rappel hein ...

scp /root/dump.sql adminservEsclave@ipservesclave:/home/adminservEsclave/dump.sql

Voilà laissons le maître de coté , passons à l'esclave ..

L'esclave:

Voilà le programme ...

  1. On vide entièrement mysql pour être sur du neuf
  2. Importation du dump
  3. Arrêt SQL_SLAVE
  4. RESET SQL SLAVE
  5. Définition du master
  6. Redémarrage du master
  7. Tests

1 nettoyage:

une simple requête :

DROP DATABASES databaseA;
DROP DATABASES databaseB;
DROP DATABASES databaseC;

2 Importation

L'importation aussi simple que l'export :

mysql -uroot -p******* < dump.sql

L'informatique compliqué ... quenéni !!!

3 Reconfiguration SLAVE

Nous voilà à l'étape de configuration de l'esclave .. commençons par le couper

mysql -uroot -p*******
STOP SLAVE;
RESET SLAVE;

Puis définissons le master (toujours dans la console mysql)

CHANGE MASTER TO MASTER _HOST='ip du maitre',
MASTER_USER='slave_user',
MASTER_PASSWORD='pwdslaveuser',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=13860;

SLAVE START;

Voyez l'utilisation du nom du fichier de logs binaires , et la position noté auparavant .
J'ai eu des soucis pour le bon démarrage de l'esclave , je suis obligé de le redémarrer complètement

STOP SLAVE;
RESET SLAVE;
START SLAVE;

4 : passons aux tests

Il faut nous assurer que l'esclave soit bien démarré , pour cela utilisez la commande sql suivant :

SHOW SLAVE STATUS;

Ce qui donne quelque chose du genre :

showslave.png

Il faut vérifier le début , à savoir :

  • Slave_IO_State soit à Waiting for master to send event
  • Slave_IO_Runnig soit à Yes
  • Slave_SQL_Running soit aussi à Yes

Ne vous reste plus qu'à tester l'évolution de la valeur de la position ( dans le log binaire ) à l'insertion d'un enregistrement sur le serveur maître ...
Ici la valeur qui doit évoluer : 972765

A savoir

  • Il est IMPERATIF de ne pas faire d'insertions sur le serveur esclave , seul les sélections sont possible, sinon , votre réplication s'arrêtera.
  • Les valeurs des screens ci dessous ne correspondent pas ensembles , pour la simple raison que les commandes pour faire cet article se sont fait sur des postes qui ne sont pas de vrai replications.


Si vous avez des commentaires , n'hésitez pas .
Ch.

Toujours est-il ,

09 fév. 2009

Transformer un script PHP en Daemon ...

standing_daemon.jpg Nous allons voir ici comment faire pour qu'un script PHP puisse devenir un "Daemon" indépendant du navigateur web , personnellement je l'utilise par exemple dans un de mes projets en tant que partie serveur , le script et lancé au démarrage du serveur , puis écoute sur un port donné , pour effectuer une tache précise à la connexion d'un client ... A vous de trouver l'utilisation adéquate d'un tel système ..

Pré-requis :

Pour créer un daemon , nous allons devoir contrôler les processus via la bibliothèque PCNTL de php , pour l'installation , il faut juste compiler PHP avec l'option --enable-pcntl , et surtout , ne pas mettre --disable-cli ni --disable-cgi , car le script qui utilise les fonctions PCNTL , doivent être lancé en CGI , ou CLI , comme expliqué dans la documentation , il vous sera donc impossible de lancer votre script à partir d'un navigateur , sauf si vous utiliser php en mode CGI/FastCGI et non , en module apache .

Le principe :

Le principe est le suivant , l'utilisateur avec pouvoir ( ici root ) lance le script principale , qui dans un premier temps "fork" le processus courant , ( il crée donc un fils identique à lui-même ) , puis le processus pére se tue "Kill" . Le fils passe en chef d'orchestre change son processus en chef de session Le fils va ensuite changer d'utilisateur afin de s'exécuter sur un utilisateur avec le minimum de droits possible ( ici ce sera nobody ) . Dans un troisième temps , le fils va déclarer ses propres méthodes à la réception d'un signal du système . Et enfin , le script peut se lancer sans problème .., indépendamment du processus pére ou du terminal qui à lancer le script ..

L'exemple :

Comme expliqué plus haut , nous allons reprendre chaque étape importante et voir le code "PHP" correspondant ... aller c'est parti ...

Forker le processus pére :

$pid = pcntl_fork();
	   
if ($pid == -1)
    {
	/* Échec du fork*/
	echo "Échec du fork!\n";
	exit();
    }elseif ($pid)
    {
	/* Termine le process père */
	exit();
    }else
    {
	/* Process Fils*/

        //Fait du processus courant un chef de session
	posix_setsid();

        //Changement du répertoire courant pour l'exécution du script
	chdir('/');

        //change le umask de PHP en 0777
	umask(0);

        //Retourne l'identifiant du processus fils
	return posix_getpid();
    }

Voilà comment creer un démon .. dans le script ci-dessus , c'est la fonction pcntl_fork() qui s'occupe de dupliquer les processus , ensuite , vous imaginez deux processus qui s'exécutent en parallèle .. l'un qui a un $pid ( le pére , car c'est la pére qui a lancé le fork ) et un autre qui n'en a pas ( le fils , car $pid n'est pas défini ) . En tue donc le pére avec la commande exit() . Le processus fils continue donc seul son chemin .. il fait du processus courant un chef de session ... via la fonction posix_setsid(); , pour ensuite changer le répertoire courant , et le mask de php , pour au finale ,retourner son identifiant .

Changer d'utilisateur

Pour des raison de sécurité , il faut changer d'utilisateur courant , car là nous somme toujours en root :

if( !posix_setgid( 65534 ) )
    {
        print "Erreur  setgid :" . $gid . "!\n";
        exit;
    }

    if( !posix_setuid( 65534 ) )
    {
        print "Erreur setuid :" . $uid . "!\n";
        exit;
    }

Voilà , pour le changement d'utilisateur , nous avons récupéré l'UID et le GID de l'utilisateur nobody pour l'attribuer au processus fils via les fonctions posix_setuid() et posix_setgid()

Les signaux :

Le script fils peut déclarer ses propres méthodes pour gérer comme il l'entend ( ou plutôt comme VOUS l'entendez ) , la réaction aux signaux systéme .

declare(ticks = 1);

/* handle signals */
pcntl_signal(SIGTERM, 'sig_handler');
pcntl_signal(SIGINT, 'sig_handler');
pcntl_signal(SIGCHLD, 'sig_handler');

/**
* Signal handler
*/
function sig_handler($sig)
{
    switch($sig)
    {
        case SIGTERM:
        case SIGINT:
            exit();
        break;

        case SIGCHLD:
            pcntl_waitpid(-1, $status);
        break;
    }
}

La gestion des signaux ci-dessus , utilise les ticks déprécié depuis php 5.3 ... il faudra donc trouver une autre alternative ... ici , la gestion des signaux n'est pas obligatoire !

Lancement :

Pour lancer votre daemon, plusieurs solutions , soit apache fonctionne avec php en mode CGI/FastCGI , alors , vous pouvez lancer le daemon via votre navigateur ( mais mauvaise idée , car de ce fait , votre navigateur doit se trouver sur la même machine que votre script et être lancer en root ), sinon, ce sera en ligne de commande , comme ceci :

En root:

php /dir/de/votre/script/serveur.php

Le script se lance puis s'arrête aussitôt .. car en faite , le script que vous lancez est le process pére .. qui dés qu'il a créé son fils , se tue !

Pour vérifier que votre daemon se trouve bien dans la liste des processus , il vous suffit de le rechercher dans les process courant , exemple pour serveur.php :

ps -xa | grep serveur.php

Qui retourne une ligne de ce style :

25951 ? Ss 0:00 php /dir/du/script/serveur.php

Voilà , en espérant avoir écrit un script intéressant , sans trop entrer dans les détails ..

Christophe.