mysqlfs mit mySQL NDB Cluster als verteiltes Dateisystem

Jeder der kritische Anwendungen über das Web laufen hat, wie z.B. einen Onlineshop, stellt sich irgendwann, bei hinreichend großem Umsatz, die Frage, wie man das System noch ausfallsicherer machen kann.

Meist wird dann hierzu ein Loadbalancer (ob Hardware oder Software ist erst mal egal) aufgesetzt, welcher die Anfragen an mehrer Server verteilt, welche sich einen gemeinsammen Massenspeicher teilen. Dadurch ist es möglich, dass einzelne Server gewartet werden können, bzw. auch ausfallen können, ohne dass die Applikation dadurch gestört wird.

Leider beschränkt sich diese Variante auf nur eine Location, d.h. wird aus irgendwelchen Gründen z.B. die Internetanbindung an das System unterbrochen, ist die Applikation offline.

Dies kann man damit umgehen, dass man das System multihomed aufbaut, d.h. mehrere Server an unterschiedlichen Standorten betreibt, um bei einem Ausfall von einem Standort trotzdem noch erreichbar zu sein. Diese Variante hat den Nachteil, dass die Daten des Systems sehr aufwändig synchronisiert werden müssen, falls ein Standort nicht mehr erreichbar war. Weiterhin muss man auch bei Updates etc. aufpassen, dass es keine Versionskonflikte bei der Applikation gibt, denn man kann die Software nicht an beiden Standorten gleichzeitig aktualisieren.

Benötigt wird für so eine Lösung also zum einen eine Datenbank, welche automatisch repliziert und dies auch über mehr als einen Standort hinweg, weiterhin dazu noch ein Dateisystem, welches verteilten Host-Systemen eine gemeinsame Datenbasis bereitstellen kann.

Zu diesem Zweck habe ich auf mehreren Test-Systemen eine solche Umgebung aufgebaut und will hier diesen Test dokumentieren. Ich habe dazu einfach 2 Systeme innerhalb eines VMware Servers erzeugt:

mysqlfsdevelop01 sowie mysqlfsdevelop02, mit folgender Konfiguration:

  • 2 GB HDD Space
  • Netzwerkkarte
  • 256MB RAM
  • CD-ROM (mit gemountetem Disk-Image Debian-Etch 4.0)

Nachdem man die Hosts in VMware angelegt hat, und Debian Etch auf diesen installiert ist, muss man noch einige Pakete nachinstallieren, mit

apt-get install build-essentials

zuerst alle benötigten Pakete installieren, damit man selbst Software kompilieren kann.

Weiterhin werden dann noch folgende Pakete benötigt:

apt-get install fuse-utils afuse libfuse-dev libmysqlclient15-dev libmysql++-dev glibc-dev mysql-server-5.0

Eine Liste aller installierten/benötigten Pakete gibt es hier

Nachdem also unser Debian auf beiden Host-Systemen installiert ist, müssen wir noch unseren mySQL Server so konfigurieren, dass auf diesem NDB läuft. Dazu müssen auf beiden Host-Systemen Änderungen an der /etc/mysql/my.cnf vorgenommen werden:

  • unter [mysqld] den Paramenter ndbcluster ohne Option hinzufügen
  • [MYSQL_CLUSTER] suchen und die Rauten entfernen
  • ndb-connectstring=127.0.0.1 kann beibehalten werden

Dann die Datei speichern. mySQL noch nicht neu starten!

Dann wird in /etc/mysql/ die Datei ndb_mgmd.cnf angelegt, und folgender Inhalt eingefügt:


[NDBD DEFAULT]
NoOfReplicas=2

[MYSQLD DEFAULT]

[NDB_MGMD DEFAULT]

[TCP DEFAULT]

# Section for the cluster management node
[NDB_MGMD]
# IP address of the management node (this system)
HostName=192.168.200.40

#IP des ersten Nodes (mysqlfsdevelop01)

[NDB_MGMD]
# IP address of the management node (this system)
HostName=192.168.200.41

#IP des zweiten Nodes (mysqlfsdevelop02)

# Section for the storage nodes
[NDBD]
# IP address of the first storage node
HostName=192.168.200.40
DataDir= /var/lib/mysql-cluster

[NDBD]
# IP address of the second storage node
HostName=192.168.200.41
DataDir=/var/lib/mysql-cluster

# one [MYSQLD] per storage node
[MYSQLD]
[MYSQLD]

Die Datei muss auf beiden Systemen angelegt werden, bei mysqlfsdevelop02 allerdings bei [NDB_MGMD] die IP des zweiten Servers angeben, so dass auf beiden Systemen ein Management-Daemon läuft.

Nun starten wir zuerst den Management-Daemon, dann die NDB-Datenbank und zuletzt restarten wir mysql selbst (als API):

/etc/init.d/mysql-ndb-mgm start

/etc/init.d/mysql-ndb start

/etc/init.d/mysql restart

Danach kann man mit ndb_mgm eine Konsole auf den NDB-Cluster öffnen. Ein “show” sollte folgenden Output erzeugen:

ndb_mgm> show
Connected to Management Server at: 127.0.0.1:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 2 node(s)
id=3 (not connected, accepting connect from 192.168.200.40)
id=4 @192.168.200.41 (Version: 5.0.32, Nodegroup: 0, Master)

[ndb_mgmd(MGM)] 2 node(s)
id=1 @192.168.200.40 (Version: 5.0.32)
id=2 @127.0.0.1 (Version: 5.0.32)

[mysqld(API)] 2 node(s)
id=5 @192.168.200.40 (Version: 5.0.32)
id=6 @192.168.200.41 (Version: 5.0.32)

Wenn dies soweit läuft, ist der erste Schritt getan.


Jetzt muss mysqlfs mit cvs heruntergeladen werden und übersetzt werden.

Dazu wechseln wir nach /usr/src und geben ein:

cvs -d:pserver:anonymous@mysqlfs.cvs.sourceforge.net:/cvsroot/mysqlfs login

und dann:

cvs -z3 -d:pserver:anonymous@mysqlfs.cvs.sourceforge.net:/cvsroot/mysqlfs co -P mysqlfs

sowie:

./cvs-bootstrap
./configure

Falls es hier Fehler gibt, kann man mit autoreconf -i –force fehlende Teile automatisch erstellen lassen – spätestens jetzt sollte das configure ohne Probleme durchlaufen.

Jetzt musst allerdings noch das mysql-Schema gepatched werden – mit der Version vom CVS wird NDB-Cluster nicht unterstüzt:

diff -Nuar mysqlfs/schema.sql mysqlfs-mrjack/schema.sql
--- mysqlfs/schema.sql 2007-03-28 15:05:48.000000000 +0200
+++ mysqlfs-mrjack/schema.sql 2008-03-31 22:59:06.000000000 +0200
@@ -25,7 +25,7 @@
`seq` int unsigned not null,
`data` blob ,
PRIMARY KEY (`inode`, `seq`)
-) ENGINE=MyISAM DEFAULT CHARSET=binary;
+) ENGINE=NDBCLUSTER DEFAULT CHARSET=binary;


— Table structure for table `inodes`
@@ -45,7 +45,7 @@
`size` bigint(20) NOT NULL default ‘0’,
PRIMARY KEY (`inode`),
KEY `inode` (`inode`,`inuse`,`deleted`)
-) ENGINE=MyISAM DEFAULT CHARSET=binary;
+) ENGINE=NDBCLUSTER DEFAULT CHARSET=binary;

/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;
DELIMITER ;;
@@ -58,16 +58,16 @@

— Table structure for table `tree`


+SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `tree`;
CREATE TABLE `tree` (
`inode` int(10) unsigned NOT NULL auto_increment,
– `parent` int(10) unsigned default NULL,
+ `parent` int(10) unsigned,
`name` varchar(255) NOT NULL,
– UNIQUE KEY `name` (`name`,`parent`),
+ PRIMARY KEY `name` (`name`, `inode`),
KEY `inode` (`inode`),
KEY `parent` (`parent`)
-) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+) ENGINE=NDBCLUSTER DEFAULT CHARSET=utf8;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;

Nun kann man mysqlfs mit make compilieren.

Anschliessend muss man das Schema in die mysql-Datenbank importieren.

Dazu zuerst die Datenbank “mysqlfs” auf beiden Servern anlegen:

mysql> CREATE DATABASE mysqlfs;
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON mysqlfs.* TO mysqlfs@"%" IDENTIFIED BY 'password';
mysql> FLUSH PRIVILEGES;

Sowie anschliessend das Schema importieren:

$ mysql -uroot -p mysqlfs < schema.sql

Dann einen Mountpoint anlegen, z.B. /mysqlfs mittels mkdir /mysqlfs

und das File-System mounten mit:

./mysqlfs -ohost=localhost -ouser=mysqlfs -opassword=password -odatabase=mysqlfs /mysqlfs

Man kann auch in der /etc/mysql/my.cnf einen Abschnitt [mysqlfs] erzeugen und diese Daten dort hinterlegen:

[mysqlfs]
host=localhost
user=mysqlfs
password=password
database=mysqlfs

Nun kann man das Filesystem einfach mit ./mysqlfs /mysqlfs mounten.

Ein “mount” gibt nun folgende Ausgabe:

mysqlfs on /mysqlfs type fuse (rw,nosuid,nodev)

Man muss mysqlfs natürlich auch auf dem zweiten, bzw. jedem weiteren Server installieren!

Wenn man nun Dateien in /mysqlfs erzeugt werden diese instantan auch bei dem zweiten Server verfügbar.

Ein Nachteil von mySQL-Fs ist jedoch, dass es relativ langsam ist, da durch mysql-ndb und fuse viel Overhead erzeugt wird. Es sei noch erwähnt, dass mysqlfs kein Locking unterstützt, weshalb man davon absehen sollte, Files mehrfach von unterschiedlichen Hosts gleichzeitig zu öffnen. Insbesondere Session-Daten etc. sind in einer mySQL-DB besser aufgehoben als ein mittels mysqlfs verteiltes /tmp/.

Es reicht allerdings aus, um z.B. PHP-Seiten zentral abzulegen und diese auf vielen verschiedenen Servern verfügbar zu machen, um z.B. ein Loadbalancing mittels DNS-Round-Robin zu realisieren.

mysqlfs ist Opensource und ist bei Sourceforge gehostet:
http://sourceforge.net/projects/mysqlfs/

2 thoughts on “mysqlfs mit mySQL NDB Cluster als verteiltes Dateisystem

  1. Pingback: |X|  MySQL
  2. Pingback:       |>> MySQL

Comments are closed.