理系学生日記

おまえはいつまで学生気分なのか

mysql-master-ha (MHA) まとめ

諸々の事情により MHA を検証・導入しようという流れがあり、イマイチまだ全体像が見えていないのでまとめてみた。

**MHA とは MySQL のマスタを failover させスレーブをマスタに昇格させるという面倒な作業を短時間(10-30 秒と言われている)で行わせることを目的としたソフトウェア。 一般に、MySQL のマスタ・スレーブ構成を 1 対多という構成で取った場合、スレーブ間でどこまでマスタの DB 状況が反映されているかには差が生じ、これが自動 failover の妨げになっていた。MHA ではこの問題 (replication consistency problem) も解決してくれる仕組みを内在しているため、運用上のスレーブ間の DB 整合性の問題からも開放される。 - ref: Google Code Archive - Long-term storage for Google Code Project Hosting.

何をしてくれるの *マスタの自動監視と自動 failover

マスタを監視し、それがコケるとマスタを failover させる機能。このときにスレーブが複数あると、最新の DB 情報を反映しているスレーブから、その他のスレーブに対してその差分を適用する動作をするため、スレーブ間のデータ整合性が保証される。 具体的は + 新マスタの選出 + スレーブ間での relay log の差分抽出・同期 + 新マスタからスレーブへのレプリケーション設定 あたりを実施してくれる。

*** 手動でのマスタ failover

手動でも failover できるよ。

*** 自動監視なしでの 自動 failover

MHA 自身では MySQL のサービス監視は実施しない。この MySQL の正常性監視を担うのは Pacemaker 等になる。Pacemaker とかでマスタの異常を検知・VIP を切り替えた上で、MHA が MySQL のマスタの failover 、スレーブの昇格を実施する。

*** MySQL マスタの別ホストへのオンラインマイグレーション

マスタの別ホストへの移動を、Write のブロック 0.5 - 2 秒で実現する。

** 動作の概要

*** マスタ故障時、マスタからスレーブに送られていない binlog event の抽出 同期が最も進んでいるスレーブの SHOW SLAVE STATUS の結果から、当該スレーブに適用されているマスタの binlog とその position が分かる。このため、このときのマスタがそれなりに正常に稼動していることを前提とすれば、mysqlbinlog --start-position=N binlogfile1 binlogfile2 ... により、スレーブに適用されていない binlog event が分かる。

*** 同期が最も進んでいるスレーブの特定の仕方 同様に、スレーブ間で Master_Log_File、Read_Master_Log_Pos を比較すれば良い。

*** スレーブ間での同期の取り方

マスタ・スレーブ間で非同期レプリケーションを取ろうが準同期レプリケーションを取ろうが、スレーブ間での同期が取れていないという状況は避けられない。従って、これらの同期を取ってやらなければ、新たに選出される MySQL マスタとのレプリケーションに支障が生じる。 これを回避するためのスレーブ間での同期の取り方としては、各スレーブが保持している relay log を地道に比較する方法を取る。 relay log の 先頭にはマスタの binlog ファイル名が、そして relay log の中に書き出されている end_log_pos がマスタの binlog の位置を表しているので、最新の relay log のこれらの値をスレーブ間で比較することで、どのスレーブはどこまでマスタと同期が取れていたかが判別できる。また、これらをスレーブ間で比較することにより、どのスレーブの状態が最も進んでいて、他のスレーブとはどれだけズレているか(どこから差分を適用すればスレーブ間で同期が取れるか)が分かる。

-ref: Automated master failover

** コンポーネント

大きく分けて Manager と Node の 2 つが存在する。

*** Manager 以下の 2 つ の機能を持つ。 + master_monitor -- MySQL マスタのサービス監視を行う + master_switch -- フェイルオーバを行う

*** Node 各 MySQL サーバ上で動作する。以下の機能を持つ。 + save_binary_logs: -- アクセスが可能な場合に限り、マスタの binlog をコピーする + apply_diff_relay_logs: -- 最新の状態にあるスレーブとの relay log の差分を抽出し、該当する差分を適用する + filter_mysqlbinlog: -- 不要な ROLLBACK イベントを削除する + purge_relay_logs: -- SQL スレッドを止めることなく、不要になった relay log を削除する

** フックポイント MHA では、その動作の各所に任意のスクリプトを実行することができるよう、全部で 6 箇所のフックポイントが用意されている (Custom Extensions) 。 + secondary_check_script -- 実際に MySQL マスタが「落ちていること」を確認するためのスクリプトを配置する。おそらくはスプリットブレインを避けるためだと思う。ここに適用するスクリプトとして、標準で masterha_secondary_check というスクリプトが同梱されており、これを

|tcsh| secondary_check_script = masterha_secondary_check -s remote_host1 -s remote_host2 ||< のように指定することで、remote_host1, 2 の双方からサービス監視 NG になった場合にのみ MySQL の failover が走る、というような振舞をさせることができる。ここで、remote_host[12] は、MHA Manager、MySQL マスタとは別セグメントに置くことが推奨。また、ここでの監視内容は TCP のコネクション確立の模様(ソース未確認)。 -- ref: Google Code Archive - Long-term storage for Google Code Project Hosting. + master_ip_failover_script -- MySQL を使用しているアプリケーションが、Failover 後の新マスタを使用できるようにするスクリプトを設定する。VIP の切り替えとか。 -- このスクリプトは、3 回に渡り呼び出されることに注意が必要。どのフェーズで呼び出されるかは、渡される --command 引数によって判断できる模様。 +++ Checking Phase: (スクリプトの有効性チェック…?) +++ Current master shutdown phase: (shutdown_script が呼び出される直前で呼び出される) +++ New master activation phase: -- スクリプトが 0 か 10 を返却する場合は Failover 続行、それ以外を返却する場合は Failover を停止する + shutdown_script -- スプリットブレインを避けるため、ダメになった MySQL マスタのサーバを shutdown するためのスクリプトを設定す -- MHA は、このスクリプトを呼び出す前に、マスタのサーバに ssh 接続を試行し、その結果によって、スクリプトに渡す引数が変更される (MySQL サーバのポートや pid ファイルが渡されなくなる)。 -- デフォルトで用意されているスクリプトの挙動は以下の通り。 --- ssh で接続可能だった場合は、-pid_file で渡された pid ファイルで示される mysqld, mysqld_safe を -9 付きで kill する。-pid_file が渡されなかった場合は全ての mysqld, mysqld_safe を kill する。 --- ssh で接続不可能だった場合は、ipmitool やら dracadm やらで、サーバごとシャットダウンを試行する。 --- ちなみに、このスクリプトは、MHA Manager が監視を始めるときにも --command=status という引数付きで呼び出される。これは、このタイミングで電源ステータスのチェックをしておけば、設定間違いとかを防げるため。 + report_script: -- failover 完了後、または異常終了後に呼び出されるフックで、email を出すなどの結果通知を意図したもの。 + init_conf_load_script: -- "name=value" という形の文字列を標準出力に返すことで、MHA の設定を行えるスクリプトを設置する。