Home > まめ知識 | 開発裏話 > MySQLの無停止レプリケーション(最強?の冗長化)〜KeepAlivedとの連携〜

MySQLの無停止レプリケーション(最強?の冗長化)〜KeepAlivedとの連携〜

序文

今回は、これまでの内容を、実践投入するべく、MySQLのレプリケーションをKeepAlivedと連携させ、自動フェイルオーバーと、無停止フェイルバックを実現させてみました。

フェイルオーバーの方は、結構簡単なのですが、問題はフェイルバック。無停止でフェイルバックさせるには・・MySQL管理者ならば誰しも当たる壁のような気がします。今回は、ちょっとサーバー台数多めですが、ほぼ完全無停止のMySQL-HAを作成します。

また、本内容は、MySQLレプリケーションのイロハは省略しております。わからないところは、他サイトにたくさん例がありますので、そちらを参考に読んでください。

構成内容

サーバー6台以上必要です。(参照系KeepAlived等をスレーブに同居させると、最小4台で済みますが、わかりやすいのは6台構成です。)構成は、MySQLサーバー4台、KeepAlivedサーバー2台です。

特徴1

一部、準同期レプリケーションを使うことで、故障時のクエリ消失が原則存在しません。これって、結構すごいことだと思うんですが・・。そんなわけで、準同期レプリケーションを使うので、MySQL5.5以降をお薦めします。また、非同期でも、ほぼクエリ損失はありませんでしたので、5.1系でも十分に使えると思います。(サーバー管理者としては、枯れた方を採用しなければならない局面があるので、準同期が使えなくても、実戦投入できるのはいいですね。)もちろん、何の保証もしませんので、実際に採用される場合は自己責任でお願いします。

特徴2

アプリケーション側で、参照クエリ、更新クエリの問い合わせ先を変えていることが前提です。MySQL参照系クエリは、レプリケーションされた3台のサーバーに振り分けますので、無駄はありません。また、再起動時に勝手にMySQLが立ち上がらないようにchkconfigはoffにしておくことをお薦めします。

構成図

次のようになります。

簡単な概要は次の通りです。

名前 稼働パッケージ 概要
Master MySQL、KeepAlived SubMasterとのVRRP連携してます。KeepAlivedのVIPで、更新系クエリを受け付け、SubMasterに準同期でレプリケーション、slave1-1に非同期レプリケーションします。また、KeepAlivedを使って、自身のMySQLの死活監視も行っています。自身のMySQLが応答しない場合は、KeepAlived及びMySQLを停止させます。
slave1-1 MySQL、Cron Masterから非同期レプリケーションしています。複数台にできます。Cronを用いて、自身のレプリケーション監視を行っています。レプリケーション停止時は、自身のMySQLを停止させます。
SubMaster MySQL、KeepAlived MasterとVRRP連携してます。マスタが停止したら自動的にマスタに昇格します。こちらも、KeepAlivedを使って自身のMySQLの死活監視を行っています。自身のMySQLが応答しない場合は、KeepAlived及びMySQLを停止させます。
slave2-1 MySQL、Cron SubMasterから非同期レプリケーションしています。複数台にできます。Cronを用いて、自身のレプリケーション監視を行っています。レプリケーション停止時は、自身のMySQLを停止させます。
KeepAlived Mst KeepAlived KeepAlived Slvと、VRRP連携を行っています。参照系クエリの受付と、分散をDSR構成で行います。
KeepAlived Slv KeepAlived KeepAlived Mstと、VRRP連携を行っています。KeepAlived Mstが停止すると、自動的にKeepAlived Mstに昇格します

構築の前に、フェイルオーバーとフェイルバック挙動について説明します。

slave*-*停止時

※どのslaveでも、挙動はほとんど変わりません。例として、slave1-1が停止した場合を書きます。

フェイルオーバー

1.(自動)Slave1-1のMySQLが停止。

2.(自動)参照受付のKeepAlived Mstが、バックエンドのslave1-1が停止していることを検知し、参照クエリを、SubMasterとslave2-1に振る。

フェイルバック

1.(手動)Slave1-1を再起動。

2.(手動)レプリケーションが追い付くまでは、危険なので、slave1-1のiptablesの設定等で、参照系クエリがslave1-1に飛んでこないように設定。たとえば下のようにレプリケーション以外のパケットをブロックするとかです。

iptables -A INPUT -s 192.168.0.30 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP

3.(手動)レプリケーションが追い付いたのを確認後、パケットブロックの解除等で、参照クエリの受付を開始する。(ブロック解除で自動復帰)

4.(手動)お・わ・り!

フェイルバックは、至って簡単です。

サブマスタ(SubMaster)停止時

※サブマスタのMySQLのみが停止しても、サブマスタ自身が落ちても、ほぼ同一の挙動をとります。

フェイルオーバー

1.(自動)SubMasterのMySQLが停止。

2.(自動)SubMasterのKeepAlivedが自身のMySQLが落ちたことを検知し、自分自身であるKeepAlived停止と、MySQLが固まっていたとき用に、MySQLも停止。

3.(自動)slave2-1がレプリケーション停止を感知し、自身のMySQLを停止。

4.(自動)参照受付KeepAlived Mstが、バックエンドのSubMasterとslave2-1が停止していることを検知し、参照クエリを、slave1-1のみに振る。

フェイルバック

※基本的に、slaveが停止したときと同様です。再生の順番に気を付けてください。

1.(手動)SubMasterの再起動。

2.(手動)SubMasterをレプリケーション以外パケットブロックして、レプリケーションを追い付かせる。

3.(手動)パケットブロックを解除して、参照クエリを受付開始する。(ブロック解除で自動復帰)

4.(手動)KeepAlivedの起動。

5.(手動)Slave2-1だけ落ちているものとして復旧させる。

6.(手動)お・わ・り!

KeepAlived Mst停止時

※KeepAlived Slvが停止した場合は、単純に再起動させるだけです。

フェイルオーバー

1.(自動)KeepAlived Slvが、VRRPによりKeepAlived Mstが停止したことを検知し、参照系VIPアドレス(図の場合192.168.0.2)を引きついでファイルオーバー(参照系の通信断が数秒発生。)

フェイルバック

1.(手動)KeepAlived Mstの再起動。

2.(手動)KeepAlivedを起動。(バックアップとなり、KeepAlived MstとSlvが元々と入れ替わった状態になる。)

3.お・わ・り!

Master停止時

※こいつが一番の肝であり、MySQLをバックエンドに使用している方の大半が苦労されているところだと思います。

フェイルオーバー

1.(自動)MasterのMySQLが停止。

2.(自動)MasterのKeepAlivedが自身のMySQLが落ちたことを検知し、自分自身であるKeepAlived停止と、MySQLが固まっていたとき用に、MySQLも停止。

3.(自動)SubMasterのKeepAlivedが、VRRPにより、MasterのKeepAlivedが停止したことを検知し、更新系VIP(図では192.168.0.1)を引き継いで、フェイルオーバー。この後の更新系クエリは、すべてSubMasterが受け取って処理する。

4.(自動)slave1-1がレプリケーション停止を感知し、自身のMySQLを停止。

5.(自動)参照受付KeepAlived Mstが、バックエンドのSubMasterとslave2-1が停止していることを検知し、参照クエリを、SubMasterとslave2-1に振る。

フェイルバック

※ここが、今回の構成の最も優れたところです。ほぼ、無停止、かつ簡単にフェイルバックが終了します。

1.(手動)アクセス量が少ない時間を見計らって、Slave2-1のMySQLを停止。

2.(手動)Slave2-1のMySQL-DBデータをMasterとSlave1-1に送り、データを同期させる。

3.(手動)Slave2-1を、SubMaster以外パケットブロックし、MySQLを起動させ、レプリケーションを追い付かせる。

4.(手動)Slave2-1のレプリケーションが追い付いたのを確認後、パケットブロックを解除して、参照系受付に復帰させる。(ブロック解除で自動復帰)

5.(手動)SubMasterのレプリケーションをオフにする。

>stop slave;

6.(手動)Masterを再起動し、SubMaster以外パケットブロックし、MySQLを起動させる。

7.(手動)MasterのレプリケーションマスタをSubMasterにする。

>change master to master_host='192.168.0.35',master_user='***',master_password='****',master_log_file='mysql-bin.00****',master_log_pos=****;

8.(手動)Masterのレプリケーションを開始させる。

>start slave;

9.(手動)Masterのレプリケーションが追い付いたのを確認後、パケットブロック解除。(参照には登録されていないので、参照受付は開始されない)

10.(手動)Slave1-1を再起動し、すべてのパケットをブロックし、MySQLを起動させる。

11.(手動)Slave1-1でレプリケーションのスタートポジションを変更させる。

>change master to master_host='192.168.0.30',master_user='***',master_password='****',master_log_file='mysql-bin.00****',master_log_pos=****;

12.(手動)一旦Slave1-1のMySQLを停止させ、Masterからのパケットのみを許可し、MySQLを起動。

13.(手動)Slave1-1のレプリケーションが追い付いたことを確認後、パケットブロック解除し、参照系受付に復帰させる。(ブロック解除で自動復帰

14.KeepAlived SlvのconfigをSubMasterとMasterを入れ替えたものに変更し(事前に用意しておくと楽)、KeepAlivedを再起動。

15.KeepAlived Mstのconfigも書き換え、KeepAlivedを再起動。(参照系の通信断が数秒発生。)

16.お・わ・り!

つまるところ、「MasterとSlave1-1」の集団と、「SubMasterとSlave2-1」の集団をそっくり入れ替えてしまうというのが、今回の肝です。手順内でのダウンタイムは、何と「数秒」以下です。

MasterとSubMaster間に準同期レプリケーションを組む理由

MySQLのレプリケーションは標準で非同期です。これにより、例えば、Masterで更新クエリがCommitされた直後にMasterが落ちた場合、Slaveに更新クエリがいっていないことがあります。KeepAlivedfが自動フェイルオーバーを行った場合に、その後の更新系クエリで異常がでる可能性もあります。

準同期レプリケーションでは、「Commitされる前に、Slaveに更新クエリ内容が渡っている」ことが確実になります。このため、Masterが落ちても、Commitされたクエリは、すべてSlave(今回の場合はSubMaster)に渡っていることが保証されますので、フェイルオーバーしても、Commitされたクエリの欠落が起こらないようになります。(これは安心して寝れますね。)

次回は、この構成についてのそれぞれのconfigや監視スクリプト等を公開したいと思います。

それでは、皆さん、メリークリスマス。(か、よいお年を!)

Comments:0

Comment Form

Trackbacks:0

Trackback URL for this entry
http://dev.tapweb.co.jp/2010/12/303/trackback
Listed below are links to weblogs that reference
MySQLの無停止レプリケーション(最強?の冗長化)〜KeepAlivedとの連携〜 from tap dev blog

Home > まめ知識 | 開発裏話 > MySQLの無停止レプリケーション(最強?の冗長化)〜KeepAlivedとの連携〜

Search
Feeds

Return to page top