MySQL Clusterの導入

久しぶりのblog更新。以外にWeb上の記事が少ないこともあって、今回はMySQL Clusterについて触れたいと思う。一通りの機能を解説するのには時間がかかりそうなので、数回に分ける予定。今回はまずは基本的な特徴の紹介と構築手順について。今後は最近機能拡張が行われたディスクベース・クラスタテーブルやバックアップ、リカバリについても触れていきたい。

MySQL Clusterって?

  • 生い立ち・特徴
    • 2003年にMySQL AB社がNDB Clusterを開発していたアルザード社を買収し、MySQLのストレージエンジンの1つとしてMySQLに組み込まれた。 元々MySQLとは別製品であり、mysqld単独では動作しない。Data Node(データノード)、SQL Node(=mysqld。SQLノード)、Management Node(管理ノード)の3要素で構成される。外部クラスタ製品を必要としないDBクラスタであるのが特徴。OracleRACとは違いクラスタウェアは不要。RACとの決定的な違いは、Shared DiskではなくShared Nothingであること。ミッションクリティカルな分野で導入実績が多く、レプリケーションよりも可用性が高い。現在リリースされているバージョンでは、サポートされるプラットフォームはLinuxとMAX OS Xのみ。Windowsへの移植については現在MySQL ABにて対応中という状態。
    • 実際に使用する場合の構成としては、SQLノードの下図だけ更新系処理の受け口が増えるので、専用アプライアンスLVSなどのL4 ロードバランサの下にぶら下げることで更新系負荷の分散が可能になる。最小構成はRAC同様2台で、この場合には3種類の各ノードを同じ機体に混在させることになる。レプリケーションを使ったマルチマスタ構成の場合には、アプリの設計・実装時から更新系処理の内容やDBの論理設計時に色々な考慮が必要になるが、MySQL Cluster の場合にはクラスタリング対象のデータはデータノードがうまく処理してくれるので、こういった部分についてはアプリ設計では考慮不要なのが嬉しいところ。
    • ただし、システムの規模やストレージエンジン依存の制限事項もあるためシステムの特性によってMySQL Clusterとレプリケーション、どちらがよいのかは異なるため、構成設計時には十分な検討が必要と思われる。
  • 開発ロードマップ
    • MySQL 5.1.23からData Nodeの部分が「MySQL Cluster CGE(Carrier Grade Edition) 6.2」として別リリースされ、MySQL Cluster 6.2系として扱うようになった。MySQL 5.1.24からはMySQL Clusterは通常のMySQLには含まれなくなっている(完全に別製品として分離された)。
  • NDB ClusterからMySQL Clusterへ
    • MySQL Clusterの元であるNDB Clusterでは、Data Nodeに対してアプリケーションからの接続はAPIの提供のみ。API部分をmysqldに置き換えたものがMySQL Clusterとなる。MySQL ClusterでもAPIは以前のままサポートされる。


  • 3つの構成要素(Node)の役割
    • Management Nodeは、クラスタを制御する管理ノード。クラスタに所属する各データノードの状態監視、起動停止、バックアップ・リカバリなどを行うノードである。特別なスペックは必要なく、破損しても比較的容易に再構築が可能。ただし、破損している間は外部からのクラスタ操作ができないため、多重化しておくのが望ましい。ただし、管理ノードが壊れてもクラスタが即時停止することはない。
    • SQL Nodeは、アプリなどからの「リクエストを捌く」機能をもつ。実体は通常のMySQLサーバであり、クラスタテーブルの実データはSQLではなくデータノードに保持される。クラスタ用テーブル以外のテーブルも使用する場合には、クラスタテーブル以外のデータ(MyISAMInnoDBなど)はSQLノードが持つことになる。クラスタテーブルを主体で使用するのであれば、SQLノードにはそれほど大容量な物理メモリは必要ない。
    • Data Nodeは、クラスタテーブル(NDBストレージエンジン型で作られたテーブル)の実データを格納するノードである。Node Groupと呼ばれる単位で同一のデータを保持するのが特徴。当初はクラスタテーブルのデータはオンメモリのみであったが、最近はディスクベースでのデータ保持も可能になった(この場合にもインデックスはオンメモリとなる)。ただし、元々オンメモリのみの対応であり、まだディスクベースは苦手な感あり。データノードには大容量の物理メモリの搭載が必須。なおオンメモリのクラスタテーブルのデータが消失しない仕組みは、正常に停止される場合にはディスク上にデータとして格納され、起動時にはこれをメモリ上に再ロードするためである(起動時の動きはHEAPテーブルの使い方に似ている)。


    • データ保持・・・デフォルトではオンメモリでデータを格納。全てのデータが同期される。
    • 更新処理・・・ Transaction Coodinaterにクエリが割り当てられ、このノードがデータを保持する複数のノードの全てのデータを確認、更新することでデータの完全性を保証する 。Transaction Coodinaterの役割は、全Data Nodeが持ち回りで担当。Transaction Coodinaterの役割スイッチのトリガは、トランザクションのCOMMITまたはRollBackとなる。
    • 参照処理・・・参照先のデータを保持するData Nodeのうち、Flagment(優先度付け)のあるData Nodeのデータを参照する。


MySQL Cluster導入手順

MySQL ClusterはManagement Node、SQL Node、Data Nodeの3要素から成り、一般的にはこれらは別のマシンで実行するが、今回は便宜上最小構成での構築とするため、以下のような2台構成で構築を行ってみる。db03にはクラスタ管理ノード、SQLノード、データノードの3役、db04はSQLノードとデータノードの2役とし、VMWareで構築。

ではインストールから。ここでは、RPM版ではなくNON RPM版(tarball版)を使用して構築していきたいと思う。使用する環境はCentOS 4.7 32bit(2.6.9-78.0.1.ELsmp)、MySQL Clusterは6.3.17を採用。一応今回はMySQL製品は何も導入されていないことを前提とする。まずはMySQL Cluster用のOSユーザ・グループを準備。インストール作業は2台のノード両方で行う。


# groupadd mysql
# useradd -g mysql -d /var/lib/mysql mysql
# passwd mysql
続いて、MySQL Clusterのバイナリをダウンロードしインストール。コンパイルなども不要で簡単。今回はSQLノードとしても動作させるためMySQLサーバのデータ保管領域が必要になるが、これはデフォルト(?)のまま/usr/local/mysql/dataとしておく。

# cd /usr/local/src
# wget http://dev.mysql.com/get/Downloads/MySQL-Cluster-6.3/mysql-cluster-gpl-6.3.17-linux-i686-glibc23.tar.gz/from/ftp://mysql.mirror.kangaroot.net/pub/mysql/
# tar -xzf mysql-cluster-gpl-6.3.17-linux-i686-glibc23.tar.gz -C /usr/local/
# cd /usr/local/
# ln -s mysql-cluster-gpl-6.3.17-linux-i686-glibc23/ mysql
# chown -R root.mysql mysql-cluster-gpl-6.3.17-linux-i686-glibc23/
# chown -R mysql.mysql mysql/data/
インストールしたMySQLのbin配下(/usr/local/mysql/bin)にPATHを通しておく。

# cp -p ~/.bash_profile ~/.bash_profile.orig
# vi ~/.bash_profile
# diff ~/.bash_profile ~/.bash_profile.orig
10c10< PATH=$PATH:$HOME/bin:/usr/local/mysql/bin

    • -

> PATH=$PATH:$HOME/bin
# . ~/.bash_profile

MySQLの管理DB初期化とMySQLの起動スクリプト配備を実施。これでインストールは完了。なんて簡単。

# cd /usr/local/mysql
# ./scripts/mysql_install_db --user=mysql
# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql
# chown root.root /etc/init.d/mysql
# chmod u+x /etc/init.d/mysql
続いて、MySQL Clusterを使用するための設定をしていく。まずは管理ノード用の設定から。管理ノードの設定はdb03号機に対してのみ行う。なお、設定ファイルの場所は任意でよい。

# mkdir /var/lib/mysql-cluster
# chown -R mysql.mysql /var/lib/mysql-cluster
# cd /var/lib/mysql-cluster
# vi config.ini
今回は動作するために最低限必要な設定のみの紹介とするため、ほぼカスタマイズなしの構成。注意事項として、設定値にホストを指定する際、設定ファイル内で「ホスト名での記述とIPアドレスでの記述が混在してはならない」という制約がある。ホスト名で指定する場合には、DNS、/etc/hostsなどで確実にリモートホストの名前解決が行えるようにし、設定ファイル内の指定を全てホスト名での記述に統一すること。

[NDB_MGMD]
hostname=192.168.1.113 # Management Node(クラスタ管理ノード)の指定

[NDBD default]
NoOfReplicas=2 # データを何重に冗長化するかを指定
datadir=/var/lib/mysql-cluster # MySQL Cluster用データ(NDBテーブル)格納先

[NDBD]
hostname=192.168.1.113 # データノードを指定。ノード数だけ「[NDBD]セクションを記述」

[NDBD]
hostname=192.168.1.114 # データノードを指定

[MYSQLD]
hostname=192.168.1.113 # SQLノードを指定。ノード数だけ「[MYSQLD]セクションを記述」

[MYSQLD]
hostname=192.168.1.114 # SQLノードを指定

次に、db03、db04両サーバに対してSQLノード(MySQLサーバ)の設定を行う。以下のように/etc/my.cnfを設定。ただし、ここでは最低限の設定のみを行っているため、実運用では必要なパラメータを適切に設定する必要があるので注意。ndb_connectstringには、クラスタ管理ノードのIPアドレスを指定する。

# cat /etc/my.cnf
[mysqld]
ndbcluster

[mysql_cluster]
ndb_connectstring=192.168.1.113

[ndb_mgmd]
config_file=/var/lib/mysql-cluster/config.ini

MySQL Clusterの起動

MySQL Clusterの起動は、必ず以下の手順で行う必要がある。停止手順は基本的にはこの逆。

  • 1.Management Nodeの起動
  • 2.Data Nodeの起動
  • 3.SQL Nnodeの起動

では、順に起動していく。まずはdb03号機で管理ノードを起動。起動時にdb03号機上で管理ノードとデータノードが起動している旨の警告が出るが、問題はないのでそのまま無視する。起動前にMySQL Clusterのデータディレクトリに移動しているのは、MySQL ClusterのログがManagement Nodeを起動したディレクトリに出力される仕様であるため、管理上わかりやすくする意味で行っている(なお、管理ノード、データノードの停止方法はプロセスKILL)。


# cd /var/lib/mysql-cluster/
# ndb_mgmd
Warning line 18: Cluster configuration warning:
arbitrator with id 1 and db node with id 2 on same host 192.168.1.113
Running arbitrator on the same host as a database node may
cause complete cluster shutdown in case of host failure.
管理ノードの起動が終わったら、続いてデータノードの起動。データノードはdb03号機、db04号機で起動する。「--initial」オプションをつけることで、以前のMySQL Clusterのログがクリアできる。今回は初回起動だが、念のため付けておく。

# ndbd --initial
正常にデータノードが起動したら、最後にSQLノードを起動する。と言ってもSQLノードは普通のMySQLサーバなので、以下のコマンドで起動するだけ。

# /etc/init.d/mysql start
管理ノード上の管理クライアント(ndb_mgm)を使用してクラスタの状態を確認してみる。

# ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> show
Connected to Management Server at: 192.168.1.113:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 2 node(s)
id=2 @192.168.1.113 (mysql-5.1.27 ndb-6.3.17, Nodegroup: 0, Master)
id=3 @192.168.1.114 (mysql-5.1.27 ndb-6.3.17, Nodegroup: 0)

[ndb_mgmd(MGM)] 1 node(s)
id=1 @192.168.1.113 (mysql-5.1.27 ndb-6.3.17)

[mysqld(API)] 2 node(s)
id=4 @192.168.1.113 (mysql-5.1.27 ndb-6.3.17)
id=5 @192.168.1.114 (mysql-5.1.27 ndb-6.3.17)

では、MySQL Clusterが動作していることを簡単に確認してみる。MySQLクライアントでdb03号機にクラスタテーブルを作ってみよう。クラスタテーブルの作り方もいたって簡単。通常のCREATE TABLE文を使用し、ENGINE句でndbcluster(またはndb)を指定するだけでOK。

# mysql -uroot -D test

mysql> create table t(a int) engine=ndbcluster;
Query OK, 0 rows affected (0.93 sec)

mysql> show table status\G
*************************** 1. row ***************************
Name: t
Engine: ndbcluster
Version: 10
Row_format: Fixed
Rows: 0
Avg_row_length: 0
Data_length: 0
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: NULL
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.01 sec)

mysql> insert into t values ('100');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t;
+------+
| a |
+------+
| 100 |
+------+
1 row in set (0.00 sec)

上記、db03号機で作成したデータが同じクラスタを構成するdb04号機に同期されていることを確認してみる。

# mysql -uroot -D test
mysql> show variables like 'hostname';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| hostname | db04 |
+---------------+-------+
1 row in set (0.00 sec)

mysql> select * from t;
+------+
| a |
+------+
| 100 |
+------+
1 row in set (0.01 sec)

まったく問題なしですね。これでオンメモリベースのクラスタテーブルを使用できる状態にするところまで、作業が完了。次回以降は、MySQL Clusterのディスクベーステーブルの使い方、バックアップ・リカバリ、管理クライアントの活用方法などについて説明したいと思います。