ちょっと硬派なコンピュータフリークのBlogです。

カスタム検索

2009-03-02

最強のMySQL HA化手法 - Semi-Synchronous Replication

MySQL 6.0で搭載される予定の機能の一つに、Semi-Synchronous Replicationというものがある。コイツを使うととんでもなく凄いHA化ができるので、今日はその方法を紹介しよう。

まずはSemi-Synchronous Replicationの機能説明から。そもそもSemi-Synchrounousってナニ?どうして完全な同期でもなく非同期でもなくSemi-Synchronousなの?という疑問をまずは解消したいと思う。さっそく次の図を見て欲しい。


これはSemi-Synchronous Replicationの動作を図で表したものである。図だけではなんだかよく分からないと思うので、以下に各ステップの詳細を説明する。
  1. アプリケーション(クライアント)からトランザクションをCOMMIT要求を出す。
  2. バイナリログを更新する。
  3. ストレージエンジン(テーブル)を更新する。
  4. それと同時にバイナリログの内容がスレーブへ送信される。
  5. スレーブがログの更新を受け取ったらマスターへackを返す。
  6. ストレージエンジンの更新とスレーブからのackを確認したらクライアントへ応答を返す。
  7. スレーブ側でログを適用する。(非同期)
これまでのレプリケーションでは、スレーブの状況は完全に非同期で、マスター側で関知することは一切無かった。しかし、Semi-Synchronous Replicationでは「COMMITが完了した時点でスレーブにもバイナリログが転送されたことをマスターが保証する」のである。スレーブ側でリレーログの内容をストレージエンジン(テーブル)へ適用するのは非同期で行われる。最後のステップが非同期なのでSemi-Synchronousと名付けられているわけである。また、ステップ3と4は並列で処理される。そのため、ネットワークが過負荷でなければCOMMIT性能に対するオーバーヘッドはとても小さく抑えられる。スレーブが複数ある場合には、スレーブから最初のackを受け取った時点でクライアントへsend_ok()が返される。

万が一マスターがクラッシュした場合でも、COMMITが完了した全てのクエリはスレーブ側に存在する。スレーブ側にフェイルオーバーしても更新が失われることは一切無い。このフェイルオーバーはとても高速である。その理由を以下に順次説明しよう。

通常のHAでは稼働系のクラッシュが発生すると次のような手順でフェイルオーバーが実行される。
  1. スレーブがファイルシステムをマウントする。
  2. MySQLサーバを起動する。
  3. InnoDBのログを調べてクラッシュリカバリ(Redo/Undo)を行う。
特にクラッシュリカバリというのが非常にくせ者で、InnoDBのログサイズが大きい場合には長時間かかってしまう。また、InnoDBのログサイズを小さく抑えたとしても数分はかかってしまうし、クラッシュ時に更新が多かった場合にはUndoの処理に時間がかかってしまう。それに比べてSemi-Synchrnonous Replicationでは、未適用のリレーログが適用されるのを待てば良い。ファイルシステムをマウントする必要もMySQLサーバを起動する必要もない。リレーログの適用はクラッシュリカバリに比べると非常に短い処理である。ちゃんとCOMMITを適切なサイズで行っていれば数秒・・・場合によっては一秒未満でフェイルオーバーが完了するだろう。まさに最強!他にかなうソリューションなし!!ダウンタイムを最小化するためにActive/Activeソリューションを利用するという必要すらなくなるかも知れないレベルである。

ちなみに、スレーブにおいて全てのリレーログの適用が完了したかどうかは、SHOW SLAVE STATUSでExec_Master_Log_PosとRead_Master_Log_Posが同じになること、またはSHOW PROCESSLISTでSQLスレッドのステータスが「Has read all relay log; waiting for the slave I/O thread to update it」になることで確認することができる。HAの皮を被せるときはこれらの情報を参照されたい。

マスターがクラッシュした場合には、スタンドアロンで利用している場合や他のHAを利用している場合と同様に、アプリケーション側でのクラッシュリカバリ処理も必要になる。クラッシュリカバリの詳細については、過去に投稿した「もしもデータベースサーバがクラッシュしたら」を参照のこと。

また、Semi-Synchronous Replicationを利用してHAを行った場合、フェイルバックにも注意が必要である。マスター側でのストレージエンジンへの更新と、スレーブへの更新の転送は並列(非同期)で行われる。そのため、マスターにだけ存在するデータやスレーブにだけ存在するデータが発生してしまうという不整合な状況がまれに生じてしまう。そのような状況が想定されるため、一度フェイルオーバーが発生したときはマスターへデータをコピーし直す必要が生じるだろう。コピーをし直すとはつまり、スレーブからフルバックアップを取得してマスタへリストアするということである。バックアップの方法はLVMスナップショット、InnoDB Hot Backup、mysqldumpなどを利用すれば良い。負荷が少ないときを見計らって作業を実施するといいだろう。

ちなみに、スレーブ側にさらにスレーブ(孫スレーブ)をつけておけば、その孫スレーブからマスターへリストアを行うことが可能になる。孫スレーブをつけておけば2重障害にも対応できるというメリットがあるため、Semi-Synchronous ReplicationによるHAを運用する場合には孫スレーブの設置を検討しよう。(孫スレーブを設置するにはスレーブにおいて--log-slave-updatesオプションを利用するため、スレーブへのフェイルオーバー時にはFLUSH LOGSをする必要があるだろう。)


Semi-Synchronous Replicationは、MySQL 6.0から搭載される予定の機能なので、現行バージョンのMySQL 5.1では利用できない。そんなの待てないよ!という人はぜひPreview版を利用しよう。Preview版は下記のページに入手方法が載っている。
https://code.launchpad.net/~hezx/mysql-server/semi-sync-replication

Semi-Synchronous Replicationは元々GoogleのMark Callaghan氏とWei Li氏の手によって開発された。MySQL 6.0では、その機能をプラグイン化して提供する予定である。素晴らしい機能を提供してくれたGoogleの諸氏に感謝したい。

参考資料:
http://dev.mysql.com/doc/refman/6.0/en/replication-semisync.html
http://forge.mysql.com/wiki/ReplicationFeatures/SemiSyncReplication
http://code.google.com/p/google-mysql-tools/wiki/SemiSyncReplication

0 コメント:

コメントを投稿