More info...

2008-12-31

2008年を振り返って・・・MySQL Cluster 6.3

2008年はMySQLにとっては激動の一年であり、実に様々なできごとがあった。その中でも特に大きなニュースといえば、
  • Sun Microsystems IncによるMySQL AB買収。
  • Drizzleプロジェクト立ち上げ
  • MySQL Clusterの分離
  • MySQL 5.1リリース
  • MySQL User Conference Japan 2008開催
だろう。UCJ2008の資料はイベントのホームページからダウンロードできるので、是非入手して見て欲しい。
http://jp.sun.com/company/events/mysql/report.html

この中で、個人的にもっとも刺激的なニュースを挙げると、MySQL Clusterの分離だろう。

MySQL Clusterは依然としてMySQLとセットでリリースされているが、基本的にはMySQLとは違うペースで開発が進むことになった。そのおかげでかなりMySQL Clusterの開発がスムーズに行われている。GA版の最新バージョンはMySQL Cluster 6.3.20だが、6.3シリーズ自体は2007年7月に開発が始まってから(フォークしてから)既にリビジョンが20にも及んでいる。ちなみに、6.3シリーズのGAバージョンは6.3.13(2008年4月リリース)だが、これはソースコードのみのリリースであった。MySQL Cluster 6.3.17(2008年8月リリース)が、バイナリでリリースされた最初のGAバージョンである。

MySQL Cluster 6.4の開発も進んでいる。先日、βバージョンの6.4.0がリリースされ、ソースコードがダウンロード可能なので興味のある人は是非使ってみて欲しい。6.4といえば、ベンチマークにおいて1ノードで秒間100万回近いReadを達成している化け物のようなDBMSである。ただし、これはNDB APIを利用してアクセスした場合の話なので、間にMySQLサーバ(SQLノード)を挟んでしまうとパフォーマンスは低下してしまうだろう。ただし、その場合のボトルネックはSQLノードになので、SQLノードの数を増やせばデータノードの性能をフルに発揮させることが出来る。

MySQL Cluster 6.4.0では次の機能が利用可能である。
  • オンラインノード追加(待ってました!!)
  • マルチスレッド化されたデータノード
  • Windowsサポート
  • バックアップ機能の改善
残念ながらNDB$INFOは搭載が見送られた。次のリビジョンで利用可能になるだろう。さて、MySQL Cluster 6.4.0をセットアップする際には注意点が二つある。

一つは、ndb_mgmdに--configdirというオプションが追加されたこと。実は、管理ノードはシステムのステータスを記憶するようになった。configdirにはステータス情報や構成情報が格納される。config.iniを再度読み込ませるには、--reloadオプションが必要になる。

もう一つは、マルチスレッド化されたデータノードの使い方である。コマンド名はndbdではなくndbmtdに変わっている。ndbdを起動してしまうとこれまで通りシングルスレッドのデータノードが起動するので注意。コマンド名に合わせてセクション名も[NDB]ではなく[NDBMTD]に変わっているので、config.iniを書き換える必要がある。ndbmtdのスレッド数はMaxNoOfExecutionThreadsオプションで指定する。[NDBMTD DEFAULT]セクションに記載しておこう。指定できる値は、2、4、8のうちどれかである。ホストのコア数と同じ数を指定するといい。

待望の新機能を搭載した6.4のせいで、すっかり影が薄くなっている感のある6.3だが、こちらのバージョンにも負けず劣らず新機能が多数存在する。新機能の数だけで言うと6.4よりも多いぐらいだ。6.4が正式にリリースされるのはまだまだ先であるし、せっかくの6.3の新機能をより多くの人に知ってもらいたい。そこで、今日は今年最後のブログの締めくくりとして、6.3で追加された機能の一つを紹介したいと思う。

MySQL UCJ2008にはMySQL Clusterのセッションが2つあり、双方ともMySQL 6.2を使ってベンチマークを行っていた。2つのベンチマーク結果では、データノードが増えると性能が頭落ちになったり、逆に性能が劣化したりしている。これは何故だろうか?シェアードナッシング型アーキテクチャであれば、理論的にはデータノードの台数に応じて性能が向上するべきである。なぜそうならないかというのは、SQLノードがデータノードにアクセスするパターンに起因する。そして、その問題はバージョン6.3でかなり改善しているのである。まずは、MySQL Cluster 6.3で実装されたDistribution Awarenessという機能から見てみよう。

Distribution Awarenessとは、日本語に訳すと「分散の意識」とでも言えるだろうか。より自然な言い方をすると「分散を意識した処理」というのもアリだろう。

MySQL ClusterのSQLノードにおいてトランザクションを開始すると、SQLノードは一つのデータノードを「トランザクションコーディネータ」として選択する。そして、トランザクションの開始から終了までを、トランザクションコーディネータ(以下TC)がSQLノードに対する窓口となって対応するのである。

SQLノードはどのようにしてTCを選択するのだろうか?バージョン6.2ではラウンドロビン(順繰りに)でTCを選択する。特定のデータノードをTCとして選択したら、そのノードを立て続けに8回TCとして選択し、すると9回目は次のノードをTCとして選択する。そしてその次のノードを8回TCとして選択し・・・という具合だ。この方法はもちろん最適なノード選択法ではない。TCとして選択されたデータノードに目的の行が存在しなかった場合などは性能上のペナルティが発生するからだ。例えば次のようなクエリを考えよう。

mysql> SELECT ...略... FROM t1 WHERE ID=123456;

このクエリの何が問題なのだろうか?IDがPRIMARY KEY(以下PK)だとすると、ID=123456の条件に合致する行は1行だけである。テーブルt1のデータはPKのハッシュ値を元にして各ノードグループに水平パーティショニングで分散しているので、ID=123456の条件に合致する行を持っているノードグループは一組だけである。もし、TCがID=123456の行を持っていたならば、このクエリはとても高速である。そうでない場合は、次の図のように無駄なネットワークトラフィックが発生してしまう。単純に倍のネットワーク通信が必要になるのである。そして、TCがID=12345の条件に合致する行を持っている確率は、データノードが増加するにつれ下がってしまう。つまり、データノードが増加すると無駄なネットワークトラフィックが増え、ネットワークがボトルネックになってしまうのである。


このような問題を解消するには、SQLノードがID=123456の行がどのデータノード上に存在するかを知っている必要がある。SQLノードがどのデータノード上に目的の行が存在するかを知るための仕組みが、Distribution Awarenessなのである。PK以外のカラムに対してDistribution Awarenessを利用するには、テーブル定義を少し工夫する必要がある。具体的な例を挙げると、上記のクエリでDistribution Awarenessを利用するには次のようにPARTITION BY KEY句によって、明示的にパーティションを設定する必要がある。

mysql> CREATE TABLE t1 (...略..., PRIMARY KEY (ID)) ENGINE NDB PARTITION BY KEY (ID);

従って、ただ単にベンチマークツールを用いただけではDistribution Awarenessのメリットを享受することは難しいが、実際のアプリケーションで利用する場合や、チューニングを施した上でベンチマークを行う場合には有効な手法であると言える。また、Distribution Awarenessは、範囲検索などではその効果は得られない。(ハッシュ値を使った場合に出来る操作は等価比較だけで、範囲検索を行う事が出来ないからだ。)

だったらDistribution Awarenessなんて大したことないよね?!と思ったそこのアナタ!!MySQL Cluster 6.3の実力を舐めてもらっては困る。6.3の真の力はまだまだこんなものではない。さらにもう一つ、TC選択時の最適化が盛り込まれているのである。それが、ndb_optimized_node_selectionオプションだ。

MySQL Clusterでは、予算やスペースの関係でSQLノードとデータノードを同居させることが多い。下記の図のようにである。


この場合、SQLノードと同じホストにあるデータノードをTCとして選択するととても効率がいい。何故ならば、他のホストとNICやネットワークスイッチを介して通信を行うよりも、同じホスト内にあるプロセス同士がループバックデバイスを用いて通信を行う方が遙かに高速だからだ。そう、ndb_optimized_node_selectionオプションはSQLノードが同じホスト内のデータノードをTCとして選択するように調整するためのオプションなのである。こうすることでネットワークの通信を一回分減らせるので、かなりの性能向上が見込まれる。

さらに工夫が見られるのは、ndb_optimized_node_selectionオプションはDistribution Awarenessとも併用できることである。ndb_optimized_node_selectionオプションは0、1、2、3の値を指定できる。それぞれの値の意味は次の通りである。
  • 0: 最適化を行わない。6.2までの挙動と同じで、8回ずつ順番に(ラウンドロビンで)各データノードをTCとして選択する。
  • 1: 常に最も近くにあるデータノード(同じホストに存在するものが最も近い)をTCとして選択する。
  • 2: Distribution Awarenessを優先的に利用する。ただし、範囲検索などDistribution Awarenessを利用できない場合には、0と同じ動作をする。
  • 3: Distribution Awarenessを優先的に利用する。ただし、範囲検索などDistribution Awarenessを利用できない場合には、1と名時動作をする。
つまり、SQLノードとデータノードを同じホストに置いた場合には、オトコは黙って3を指定しろ!ということである。

ここまで話しておいてちゃぶ台を返すようだが、上記のボトルネックはデータノード間の通信に起因するものなので、より高速なSCIなどのインターコネクトを利用すると改善される。なので6.2でもSCIを使えばデータノードの台数に応じてさらにスケールするようになり、「なーんだ。別に6.2でもいいんじゃん!」と思うかも知れないが、それでも6.3の方が安定性・速度共に勝っているので、まだ6.2を利用しているという人は6.3へのアップグレードを検討して欲しい。
それでは今年の更新はここまで!!皆さんよいお年を!!

0 件のコメント:

コメントを投稿