J’ai souvent abordé sur ce blog les différents moyens de disposer de données redondantes dans une architecture en Haute-disponibilité.
Aujourd’hui je vais vous présenter une solution un peu plus méconnue pour certains d’entre vous, mais qui mérite tout son intérêt.
MogileFS est un système de fichier distribué en mode user.
Philippe Nicolas, sur son blog, en donne une définition parfaite :
« MogileFS est une émanation de Danga Interactive, acquis par Six Apart, qui pour ses projets de développement Web a mis au point ses propres souches logicielles.
MogileFS est un système de fichiers distribué open source en mode user, attention non conforme au standard POSIX, complètement redondant offrant un mécanisme de réplication de fichiers,
sans contrainte de systèmes de fichiers locaux, dont l’esprit est un mode shared-nothing par simple agrégation de machines indépendantes.
L’approche est asymétrique avec la notion de noeuds de stockage, de machines dites « trackers » et de machines database sachant que certains de ces fonctions peuvent résider sur le même système.
L’évolutivité vient de ce « collage » de machines afin de constituer un ensemble de taille importante.
MogileFS est donc une solution simple, gratuite et facile à mettre en place sans risque de planter le système. »
Par les avantages de MogileFS :
- il agit au niveau applicatif et ne dépend donc pas d’un module du noyau
- Les trois composants de MogileFs peuvent fonctionner indépendamment et sur plusieurs serveurs
- MogileFS gère la réplication automatisée
- Il détient sa propre base d’identification des fichiers
etc…
(je vous laisse lire la présentation sur leur site http://www.danga.com/mogilefs/ et http://mogilefs.pbwiki.com/HighLevelOverview
Si vous doutez encore de ses capacités, sachez que son auteur n’est autre que Bradley Fitzpatrick qui, pour ceux qui ne le connaîtrait pas encore, fait partie de l’équipe Danga Interactive a qui l’on doit, entre autre, Memcached.
Sachez enfin que MogileFS est utilisé par Digg (220 millions de pages vues par mois…) ou la plateforme Skyrock (5 milliards de pages vues par mois), voila qui devrait piquer votre curiosité.
MogileFS est constitué de 3 composants :
- une base de données MySQL
- le « Tracker » ou client de transfert (terme bien connu chez certains 😉 )
- le noeud de stockage (mogstored)
Chaque composant est indépendant, vous pouvez donc les mixer (2 serveurs tracker+stockage, 2 serveurs stockage + 3 serveurs trackers etc….)
Concernant la base Mysql, tout dépend de votre infrastructure. Si vous disposez déjà d’une ferme Mysql, autant l’utiliser, sinon vous pouvez installer une simple solution master/slave sur 2 machines.
MogileFS, vue d'ensemble
Les prérequis sont assez importants, un serveur Mysql bien sûr et plusieurs modules Perl dont MogileFS a besoin.
Sous une Debian :
apt-get install libio-socket-ssl-perl libbsd-resource-perl libcompress-zlib-perl libnet-netmask-perl libio-stringy-perl libwww-perl
Création de l’utilisateur dédié :
useradd mogilefs
mkdir /etc/mogilefs |
useradd mogilefs
mkdir /etc/mogilefs
Je vous conseille de récupérer les dernières sources via Subversion
apt-get install subversion
cd /etc/mogilefs
svn checkout http://code.sixapart.com/svn/mogilefs/trunk/ |
apt-get install subversion
cd /etc/mogilefs
svn checkout http://code.sixapart.com/svn/mogilefs/trunk/
Récupérons les modules Perl nécessaires :
perl -MCPAN -e shell
(si vous n’avez jamais utilisé le shell CPAN, laisser les choix par défaut, et sélectionnez Europe/France puis un site FTP)
cpan> install Danga::Socket
CPAN: Storable loaded ok
...
Writing Makefile for Danga::Socket
---- Unsatisfied dependencies detected during [B/BR/BRADFITZ/Danga-Socket-1.61.tar.gz] -----
Sys::Syscall
Shall I follow them and prepend them to the queue
of modules we are processing right now? [yes]
...
Running make install
Installing /usr/local/share/perl/5.8.8/Danga/Socket.pm
Installing /usr/local/man/man3/Danga::Socket.3pm
Writing /usr/local/lib/perl/5.8.8/auto/Danga/Socket/.packlist
Appending installation info to /usr/local/lib/perl/5.8.8/perllocal.pod
/usr/bin/make install -- OK
cpan> |
cpan> install Danga::Socket
CPAN: Storable loaded ok
...
Writing Makefile for Danga::Socket
---- Unsatisfied dependencies detected during [B/BR/BRADFITZ/Danga-Socket-1.61.tar.gz] -----
Sys::Syscall
Shall I follow them and prepend them to the queue
of modules we are processing right now? [yes]
...
Running make install
Installing /usr/local/share/perl/5.8.8/Danga/Socket.pm
Installing /usr/local/man/man3/Danga::Socket.3pm
Writing /usr/local/lib/perl/5.8.8/auto/Danga/Socket/.packlist
Appending installation info to /usr/local/lib/perl/5.8.8/perllocal.pod
/usr/bin/make install -- OK
cpan>
faites de même pour
install DBI
install IO::AIO
install Path::Class
install List::MoreUtils
install Perlbal
install Gearman::Client
install Gearman::Server
install Gearman::Client::Async |
install DBI
install IO::AIO
install Path::Class
install List::MoreUtils
install Perlbal
install Gearman::Client
install Gearman::Server
install Gearman::Client::Async
Installation de MogileFS (mogilefsd, mogstored) et des outils
cd /etc/mogilefs/trunk/server
perl Makefile.PL
make
make install
cd /etc/mogilefs/trunk/
Guiguiabloc-a:/etc/mogilefs/trunk# cd api/perl/MogileFS-Client
Guiguiabloc-a:/etc/mogilefs/trunk/api/perl/MogileFS-Client#perl Makefile.PL
make install
Guiguiabloc-a:/etc/mogilefs/trunk/server# cd ../utils/
Guiguiabloc-a:/etc/mogilefs/trunk/utils# perl Makefile.PL |
cd /etc/mogilefs/trunk/server
perl Makefile.PL
make
make install
cd /etc/mogilefs/trunk/
Guiguiabloc-a:/etc/mogilefs/trunk# cd api/perl/MogileFS-Client
Guiguiabloc-a:/etc/mogilefs/trunk/api/perl/MogileFS-Client#perl Makefile.PL
make install
Guiguiabloc-a:/etc/mogilefs/trunk/server# cd ../utils/
Guiguiabloc-a:/etc/mogilefs/trunk/utils# perl Makefile.PL
Installation de la base de données
Guiguiabloc-a:~# mysql -u root -p -h guiguiabloc-mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.0.51 Guiguiabloc distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> create database mogilefs ;
Query OK, 1 row affected (0.00 sec)
mysql> grant all on mogilefs.* TO 'mogile'@'%' identified by 'password' ;
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges ;
Query OK, 0 rows affected (0.00 sec) |
Guiguiabloc-a:~# mysql -u root -p -h guiguiabloc-mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.0.51 Guiguiabloc distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> create database mogilefs ;
Query OK, 1 row affected (0.00 sec)
mysql> grant all on mogilefs.* TO 'mogile'@'%' identified by 'password' ;
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges ;
Query OK, 0 rows affected (0.00 sec)
On charge le schéma :
Guiguiabloc-a:~# mogdbsetup --dbhost=guiguiabloc-mysql --dbname=mogilefs --dbuser=mogile --dbpass=password
This will attempt to setup or upgrade your MogileFS database.
It won't destroy existing data.
Run with --help for more information. Run with --yes to shut up these prompts.
Continue? [N/y]: y
Guiguiabloc-a:~# |
Guiguiabloc-a:~# mogdbsetup --dbhost=guiguiabloc-mysql --dbname=mogilefs --dbuser=mogile --dbpass=password
This will attempt to setup or upgrade your MogileFS database.
It won't destroy existing data.
Run with --help for more information. Run with --yes to shut up these prompts.
Continue? [N/y]: y
Guiguiabloc-a:~#
Configuration de Mogstored (noeud de stockage)
Pour les noeuds de stockage, création du répertoire dédiée à cela :
Guiguiabloc-a:~# mkdir /data
Guiguiabloc-a:~# chown -R mogilefs /data |
Guiguiabloc-a:~# mkdir /data
Guiguiabloc-a:~# chown -R mogilefs /data
Puis création d »un « device » (un répertoire spécifique pour une application par exemple)
Attention, 1 device par noeud de stockage
Guiguiabloc-a:~# mkdir /data/dev1
Guiguiabloc-a:~# chown -R mogilefs /data/dev1 |
Guiguiabloc-a:~# mkdir /data/dev1
Guiguiabloc-a:~# chown -R mogilefs /data/dev1
On prépare le fichier de configuration pour le démon de stockage :
/etc/mogilefs/mogstored.conf
httplisten=0.0.0.0:7500
mgmtlisten=0.0.0.0:7501
docroot=/data |
/etc/mogilefs/mogstored.conf
httplisten=0.0.0.0:7500
mgmtlisten=0.0.0.0:7501
docroot=/data
Fichier de configuration de mogilfsd
cp /etc/mogilefs/trunk/server/conf/mogilefsd.conf /etc/mogilefs/mogilefsd.conf
#daemonize = 1
db_dsn = DBI:mysql:mogilefs:host=guiguiabloc-mysql
db_user = mogile
db_pass = password
listen = 192.168.0.1:7001
conf_port = 7001
listener_jobs = 10
delete_jobs = 1
replicate_jobs = 5
mog_root = /data
reaper_jobs = 1 |
cp /etc/mogilefs/trunk/server/conf/mogilefsd.conf /etc/mogilefs/mogilefsd.conf
#daemonize = 1
db_dsn = DBI:mysql:mogilefs:host=guiguiabloc-mysql
db_user = mogile
db_pass = password
listen = 192.168.0.1:7001
conf_port = 7001
listener_jobs = 10
delete_jobs = 1
replicate_jobs = 5
mog_root = /data
reaper_jobs = 1
Maintenant que tout cela est paramétré, lançons les services :
TRACKER :
su mogilefs -c ‘mogilefsd -c /etc/mogilefs/mogilefsd.conf –daemon’
STORAGE :
mogstored –daemon
Les commandes d’administration se font avec « mogadm ».
Vérifions les trackers (les miens écoutent sur le port 7001) :
mogadm --tracker=192.168.0.1:7001 check
Checking trackers...
192.168.0.1:7001 ... OK
Checking hosts...
No devices found on tracker(s). |
mogadm --tracker=192.168.0.1:7001 check
Checking trackers...
192.168.0.1:7001 ... OK
Checking hosts...
No devices found on tracker(s).
Maintenant, peuplons la base de données en lui indiquant les noeuds de stockages
Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.1:7001 host add Guiguiabloc-b --ip=192.168.0.2 --port=7500 --status=alive
Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.2:7001 check
Checking trackers...
192.168.0.2:7001 ... OK
Checking hosts...
[ 1] Guiguiabloc-a ... OK
[ 2] Guiguiabloc-b ... OK
Checking devices...
host device size(G) used(G) free(G) use% ob state I/O%
---- ------------ ---------- ---------- ---------- ------ ---------- -----
---- ------------ ---------- ---------- ---------- ------
total: 0.000 0.000 0.000 0.00% |
Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.1:7001 host add Guiguiabloc-b --ip=192.168.0.2 --port=7500 --status=alive
Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.2:7001 check
Checking trackers...
192.168.0.2:7001 ... OK
Checking hosts...
[ 1] Guiguiabloc-a ... OK
[ 2] Guiguiabloc-b ... OK
Checking devices...
host device size(G) used(G) free(G) use% ob state I/O%
---- ------------ ---------- ---------- ---------- ------ ---------- -----
---- ------------ ---------- ---------- ---------- ------
total: 0.000 0.000 0.000 0.00%
Il faut ajouter les « devices »:
Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.1:7001 device add guiguiabloc-a 1
Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.1:7001 device list
Guiguiabloc-a [1]: alive
used(G) free(G) total(G)
dev1: alive 0.767 2.897 3.664
Guiguiabloc-b [2]: alive
used(G) free(G) total(G)
dev2: alive 0.762 2.902 3.664 |
Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.1:7001 device add guiguiabloc-a 1
Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.1:7001 device list
Guiguiabloc-a [1]: alive
used(G) free(G) total(G)
dev1: alive 0.767 2.897 3.664
Guiguiabloc-b [2]: alive
used(G) free(G) total(G)
dev2: alive 0.762 2.902 3.664
Vous pouvez maintenant faire vos premiers tests :
Création d’un « domaine » et d’une « class » de test
(lire http://mogilefs.pbworks.com/Definitions)
Guiguiabloc-a:/var# mogadm --tracker=192.168.0.2:7001 domain add testguiguiabloc
Guiguiabloc-a:/var# mogadm --tracker=192.168.0.2:7001 class add testguiguiabloc classguiguiabloc |
Guiguiabloc-a:/var# mogadm --tracker=192.168.0.2:7001 domain add testguiguiabloc
Guiguiabloc-a:/var# mogadm --tracker=192.168.0.2:7001 class add testguiguiabloc classguiguiabloc
Faisons un petit test à la mano pour insérer un fichier
Guiguiabloc-a:/etc# mogtool --tracker=192.168.0.2:7001 --domain=testguiguiabloc --class=classguiguiabloc inject motd motd
file motd: a46d249bd6d5f650b29048b4a2e7d610, len = 357
Spawned child 9943 to deal with chunk number 1.
chunk 1 saved in 0.11 seconds.
Child 9943 successfully finished with chunk 1.
Replicating: 1 |
Guiguiabloc-a:/etc# mogtool --tracker=192.168.0.2:7001 --domain=testguiguiabloc --class=classguiguiabloc inject motd motd
file motd: a46d249bd6d5f650b29048b4a2e7d610, len = 357
Spawned child 9943 to deal with chunk number 1.
chunk 1 saved in 0.11 seconds.
Child 9943 successfully finished with chunk 1.
Replicating: 1
Une petite vérification sur nos deux noeuds de stockage nous montre que le fichier a bien était dupliqué :
Guiguiabloc-a:/etc# ls /data/dev1/0/000/000/
0000000003.fid
Guiguiabloc-b:/etc# ls /data/dev2/0/000/000/
0000000003.fid |
Guiguiabloc-a:/etc# ls /data/dev1/0/000/000/
0000000003.fid
Guiguiabloc-b:/etc# ls /data/dev2/0/000/000/
0000000003.fid
Sympa, non ? 🙂
Il ne vous reste plus qu’à utiliser la librairie cliente de votre choix (Ruby, Perl, Java, Python, Php etc…) dans votre application pour appeler vos trackers et vos fichiers stockés.
Amusez vous bien 🙂