MySQL-Cluster Howto

Aus HackerWiki

Bitmuncher

Contents

Vorwort

Dieses kleine Tutorial wird euch erklären, wie man eine MySQL-Cluster in seiner einfachsten Form, nämlich innerhalb eines abgeschlossenen Netzwerks (hier am Beispiel eines LAN), einrichtet. Ich setze hierbei Grundkenntnisse in SQL und im Umgang mit MySQL einfach mal voraus. Als Grundlage dient hier eine MySQL 4.1. Dass Linux auf allen Servern installiert sein muss, muss ich wohl kaum nochmal erwähnen, wobei die hier beschriebene Prozedur zur Einrichtung auch auf anderen Unixes ähnlich sein sollte. Doch zuerst stellt sich natürlich die Frage, wozu man ein MySQL-Cluster überhaupt braucht. Nun, diese Frage ist ganz einfach zu beantworten. Innerhalb eines Datenbank-Clusters existieren alle Daten doppelt und da (wie in allen Clustern) alle Rechner alle Daten zur Verfügung haben erreichen wir damit eine Redundanz, die eine Verfügbarkeit von 99,9% garantieren kann.

Welche Hardware

Wir brauchen fuer ein "richtiges" MySQL-Cluster mindestens 4 Rechner. Davon benutzen wir einen Rechner als Management-Konsole, 2 Server werden Speicherknoten innerhalb des Clusters und 1 Server wird uns einen API-Knoten zur Verfügung stellen (zur Begriffserklärung komme ich gleich). Die Management-Konsole dient uns zur Überwachung und Steuerung des Clusters. Da hier keine grossen Datenmengen auflaufen, muss der eingesetzte Rechner auch nicht unbedingt die Powermaschine sein. 1GHz mit 512MB RAM und einer normalen IDE-Festplatte mit 7200U/min reichen für diesen Rechner völlig aus. Die 2 Speicherknoten werden zukünfitig unsere Daten speichern und über die Management-Konsole untereinander abgleichen (spiegeln). Zu guter Letzt haben wir noch einen API-Knoten, mit dem wir auf die Daten zugreifen und auf dem üblicherweise die Programme installiert werden, die auf die DB zugreifen sollen. Da auf den Speicher-Knoten die ganzen Daten abgelegt werden und dort auch der MySQL-Daemon läuft sollten wir für diese beiden Rechnern etwas mehr Leistung einplanen. 2GHz mit mindestens 1GB RAM und einer SCSI-Festplatte (10000U/min) sind hier angemessen, wobei man aber sagen kann, dass etwas mehr RAM grundsätzlich auf DB-Servern nicht schadet. Unser API-Knoten kann von der Hardware wie ein üblicher Webserver aufgebaut sein, also 1-2GHz mit 512MB RAM und einer IDE-Festplatte (7200U/min) sind schon ganz brauchbar.Natürlich hängt die eingesetzte Hardware aber auch stark von der zu erwartenden Zugriffsanzahl auf das Cluster ab.

Installation der Software

Für das gesamt Cluster benutzen wir eine MySQL-MAX in seiner vorkompilierten Form von www.mysql.com, da wir dann sicher sein können, dass alles dabei ist, was wir für unser Cluster benötigen. Beginnen wir also mit dem einfachsten Teil, dem Einrichten der Management-Konsole. Das ist glücklicherweise schnell getan, denn wir brauchen eigentlich nur 2 Dateien aus dem Paket der MySQL-max entpacken und eine kleine Konfigurationsdatei anlegen. Downloaden wir uns also die aktuelle Version von MySQL-max und entpacken sie nach /usr/src/. Sobald dies geschehen ist, wechseln wir in das Verzeichnis /usr/src/mysql-max-4.1.x/ und kopieren aus dem dort befindlichen bin-Verzeichnis die beiden Dateien ndb_mgmd und ndb_mgm nach /usr/sbin. Als nächstes legen wir uns das Verzeichnis /var/lib/mysql-cluster an. Hier wird unser Management-Knoten zukünftig seine Daten ablegen und auch die Konfiguration für unser Cluster kommt in dieses Verzeichnis. Womit wir dann auch schon beim nächsten Punkt sind, der Konfiguration unseres Clusters. Wie im Vorwort bereits erwähnt gehe ich hier davon aus, dass das Cluster in einem eigenen abgeschlossenen Netzwerk eingerichtet wird. Dabei nehme ich folgende IP-Adressen an:

HostnameIPAufgabe
mgmt192.168.0.1Management-Knoten
ndb1192.168.0.10erster Speicherknoten
ndb2192.168.0.11zweiter Speicherknoten
api1192.168.0.20erster API-Knoten
api2192.168.0.21zweiter API-Knoten

Zuerst einmal wechseln wir in das Verzeichnis /var/lib/mysql-cluster und legen uns dort mit unserem Lieblingseditor die Datei config.ini an, die wir mit folgendem Inhalt füllen:

[NDBD DEFAULT]
NoOfReplicas=2
DataMemory=512M
IndexMemory=512M
MaxNoOfOrderedIndexes=6800
MaxNoOfUniqueHashIndexes=5200
MaxNoOfAttributes = 4000
RedoBuffer = 64M

[MYSQLD DEFAULT]
[NDB_MGMD DEFAULT]
[TCP DEFAULT]

# Management Nodes
[NDB_MGMD]
HostName=192.168.0.1

# Storage Nodes
[NDBD]
HostName=192.168.0.10
DataDir=/var/lib/mysql-cluster
[NDBD]
HostName=192.168.0.11
DataDir=/var/lib/mysql-cluster

# Setup node IDs for MySQL API servers (clients of the cluster)
[MYSQLD]
[MYSQLD]
[MYSQLD]
[MYSQLD]

Wir schliessen unseren Editor wieder und schon wird einigen sicherlich auffallen, dass unsere API-Knoten nirgends eingetragen sind. Das ist auch nicht notwendig, da wir ja in einem abgeschlossenen LAN arbeiten. Jeder korrekt konfigurierte API-Knoten in unserem LAN hat damit das Recht sich unserem Cluster anzuschliessen, was gerade in Test-Umgebungen, in denen mit verschiedenen Rechner gearbeitet wird, sich oft als nützlich erweist. Damit ist die Konfiguration unserer Management-Konsole auch schon abgeschlossen und wir können uns den Speicherknoten zuwenden. Wir loggen uns also auf dem ersten Speicherknoten (ndb1) ein und entpacken unseren Tarball der MySQL-Max nach /usr/local. Danach verlinken wir das entstandene Verzeichnis /usr/local/mysql-max- nach /usr/local/mysql und wenden uns der Konfiguration zu. Wir öffnen also die Datei /etc/my.cnf und schreiben folgenden Inhalt rein:

[mysqld]
set-variable = max-allowed-packet=2M
set-variable = key-buffer=128M
ndbcluster
default-table-type=NDBCLUSTER
ndb-connectstring='host=192.168.0.1' # Management Console
[mysql_cluster]
ndb-connectstring='host=192.168.0.1' # Management Console
[safe_mysqld]
err-log=/var/log/mysqld.log

Damit haben wir eine brauchbare Konfiguration für unser Cluster. Doch bevor alles richtig funktioniert müssen wir noch ein paar Rechte anpassen und die Default-Datenbanken 'mysql' installieren. Wir wechseln also in das Verzeichnis /usr/local/mysql und geben dort folgende Befehle ein:

# groupadd mysql
# useradd -g mysql mysql
# ./scripts/mysql_install_db --user=mysql
# chown -R root:mysql ./
# chown -R mysql data

Damit steht auch unser erster Speicherknoten. Sobald wir die gleiche Prozedur auf dem zweiten Speicherknoten wiederholt haben, ist unser Cluster jetzt bereit für den ersten Test-Lauf. Damit dies aber etwas einfacher wird, kopieren wir uns noch die Start-Skripte von MySQL nach /etc/init.d/ damit wir sie später auch gleich in die gewünschten Runlevel verlinken k&oeml;nnen.

# cp /usr/local/mysql/support-files/mysql.server /etc/init.d

Erster Start und Test des Clusters

Zuerst einmal muss die Management-Konsole bereit sein, damit die restlichen Knoten dort die Cluster-Konfiguration abholen können. Da der ndb_mgmd seine Konfiguration per Default im aktuellen Ordner sucht, wechseln wir in das Verzeichnis /var/lib/mysql-cluster und starten ihn.

# cd /var/lib/mysql-cluster
# ndb_mgmd

Mit ndb_mgm können wir überprüfen, ob er korrekt funktioniert. Nun wenden wir uns den Speicherknoten zu. Auf denen starten wir den ndbd mit

# ndbd --initial

Die Option '--inital' bewirkt, dass der Speicherknoten alle Log- und Daten-Dateien neu erstellt. Nun müssen wir nur noch die "normalen" MySQL-Serverprozesse auf den Speicherknoten starten und der Teil, der zum Speichern und Verwalten unserer Daten zuständig ist, steht.

# /etc/init.d/mysql.server start

Wir können uns nun einfach mal auf einem Speicherknoten einloggen und mit

mysql> SHOW ENGINES;

davon überzeugen, dass tatsaechlich die NDB-Engine genutzt wird. Der Output müsste dann etwa wie folgt aussehen:

+------------+---------+------------------------------------------------------------+
| Engine     | Support | Comment                                                    |
+------------+---------+------------------------------------------------------------+
| MyISAM     | DEFAULT | Default engine as of MySQL 3.23 with great performance     |
| HEAP       | YES     | Alias for MEMORY                                           |
| MEMORY     | YES     | Hash based, stored in memory, useful for temporary tables  |
| MERGE      | YES     | Collection of identical MyISAM tables                      |
| MRG_MYISAM | YES     | Alias for MERGE                                            |
| ISAM       | YES     | Obsolete storage engine, now replaced by MyISAM            |
| MRG_ISAM   | YES     | Obsolete storage engine, now replaced by MERGE             |
| InnoDB     | YES     | Supports transactions, row-level locking, and foreign keys |
| INNOBASE   | YES     | Alias for INNODB                                           |
| BDB        | YES     | Supports transactions and page-level locking               |
| BERKELEYDB | YES     | Alias for BDB                                              |
| NDBCLUSTER | YES     | Clustered, fault-tolerant, memory-based tables             |
| NDB        | YES     | Alias for NDBCLUSTER                                       |
| EXAMPLE    | NO      | Example storage engine                                     |
| ARCHIVE    | NO      | Archive storage engine                                     |
| CSV        | NO      | CSV storage engine                                         |
+------------+---------+------------------------------------------------------------+

Ausserdem sollten wir auf dem Management-Knoten nachsehen, ob beide Speicherknoten korrekt ins Cluster aufgenommen wurde.

Um uns zu überzeugen, dass auch alles funktioniert, erstellen wir einfach mal eine NDBCLUSTER-Tabelle auf beiden Knoten und fügen einen Datensatz ein.

mysql> \u test
mysql> CREATE TABLE test (i INT) ENGINE=NDBCLUSTER;
mysql> INSERT INTO test () VALUES (1);
mysql> SELECT * FROM test;

+------+
| i    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

Nun verbinden wir uns mit ndb2 und der dortigen Datenbank test und führen dort den gleichen SELECT-Befehl aus. Wir sollten auch hier das gleiche Ergebnis erhalten wie auf ndb1. Unser Cluster läuft.

Fortsetzung zur Einrichtung der API-Knoten ist in Arbeit.

Persönliche Werkzeuge