Transactd 高可用運用 (THA)
概要
Transactd バージョン 3.5 から、Transactd 高可用運用 (Transactd High Availability : THA)が利用可能になりました。 複数サーバーによるTHA冗長構成を構築すると、単一のサーバーでの運用に比べて格段にダウンタイムの少ない高可用運用を行うことができます。 また、読み取りオペレーションをスレーブで行うなど負荷分散も簡単に行うことができます。
THAは以下の特徴と機能を持っています。
- 障害検知からマスター切替・名前解決まで、フェイルオーバーに必要な処理をすべて網羅
- 障害時の最小限のダウンタイム(数秒以内)
- 自動マスターフェイルオーバー
- マスター死活監視
- 仮想ホスト名アクセスと実ホスト名解決
- OS、外部機器やDNSなどによる支援が不要
- 数行のアプリケーションプログラム変更で利用可能
- スイッチオーバー
- THAの状態検査
- MySQL/MariaDB、Linux/Windows/Mac OSX、C++/PHP/Ruby/COMなど幅広い動作環境
- Transactd PluginとTransactd client以外のライブラリは不要
目次
- THAの構成と仕組み
- THAを構築する
- THAを使用するアプリケーションの注意点
- THAの管理
- Transactd ClientとSQLアクセスの両方を使用するアプリケーションでのTHA
- haMgrリファレンス
THAの構成と仕組み
THAは、MySQLのGTIDレプリケーションを使用した、マスターと複数スレーブのサーバー構成からなります。 読取オペレーションをスレーブに分散するかどうかは自由です。 すべてのアクセスをマスターのみで行い、スレーブはフェイルオーバーのためだけにある構成でもかまいません。 スレーブは最低1台で、2台以上が望ましい構成です。
GTIDレプリケーションの使用が前提であるため、MySQL5.6以上/MariaDB 10.0以上の同一のサーバーバージョンで構成します。 GTIDレプリケーションを有効にしたレプリケーションサーバーを構築する方法は、MySQL/MariaDBのドキュメントを参照してください。
- 現在のバージョンでは、複数マスター構成はサポートされていません。マスターは単一である場合に限られます。
- データの喪失を防止するために、レプリケーションは準同期レプリケーションで構成することをお勧めします。
THAの仕組み
THAは以下の要素からなります。
- マスターサーバーとスレーブサーバー群
- ホスト名リゾルバー(THNR)
- サーバーロール
- クライアントの再接続機能
- 死活監視
- フェイルオーバープログラム(haMgr)
ホスト名リゾルバー(THNR)
THAのための、クライアントに組み込まれたホスト名リゾルバーを、THNR(Transactd Host Name Resolver)と呼びます。
THNRは簡単にアプリケーションに組み込んで使用できるホスト名の名前解決ライブラリーです。 アプリケーションは、通常のホスト名に代えて仮想ホスト名でアクセスします。 THNRはtdclcライブラリのネットワークレイヤーに組み込まれており、仮想ホスト名から実ホスト名へ変換してアクセスします。 THNRにより、OS・ネットワーク機器・DNSなどの外部装置やソフトウェアに依存せずにマスターを切り替えることが可能です。
THNRは1つのプロセスにつき1つのインスタンスで、すべてのスレッドから共有されます。
サーバーロール
一般的に、サーバーのロール(役割)はマスターまたはスレーブのいずれかです。 レプリケーションの構成からどれがマスターかは概ね判断が付きますが、将来複雑な構成に対応することを踏まえて、THAではあえてサーバー変数にロールの明示を必要としています。
フェイルオーバー時には、フェイルオーバープログラムによって各サーバーのロールが正しく変更されます。
THNRを使用したアクセスでは、クライアントが要求したロールとサーバーのロールが一致しているかを検査することで、ロールの変更を検出すると同時に、誤ってスレーブに書き込みを行うなどのトラブル防止を実現しています。
クライアントの要求するロールは、アクセスに使用されたホスト名がマスター用の仮想ホスト名かスレーブ用の仮想ホスト名かで判断されます。
クライアントの再接続機能
クライアントには、ネットワークエラーが発生した際サーバーに再接続する機能が組み込まれています。
再接続できた場合、カレントレコードやロック状態などを回復させ、あたかもエラーが無かったかのように処理を継続できます。
ただし、beginTrn()
やbeginSnapshot()
でトランザクションが開始されていた場合は、再接続は行われません。
アプリケーションはトランザクションをAbort
して、結果をユーザーに通知できます。その後のオペレーションにて再接続が行われます。
死活監視
THNRはマスターの死活監視とフェイルオーバープログラムの呼び出しも行います。 マスターがダウンしたことでクライアントにネットワークエラーが発生すると、エラー内容によって再接続がトライされます。 このとき、THNRに「再接続である」ことが通知されます。
再接続通知を受けると、THNRは現在のホスト名のキャッシュを破棄し、再度正しいホストの検出を行います。 この過程でマスターに正しくアクセスできない場合は、マスターがダウンしているとみなし、フェイルオーバープログラムを呼び出してマスターを切替え、新マスターの検出を行います。
この死活監視はクライアントアクセスのエラーをハンドリングすることで行います。これによって以下のような効果があります。
- 定期的な監視のためのポーリングが不要。
- ポーリングによるサーバー負荷がない。
- 障害発生から検出までのタイムラグがない。
- 障害発生から検出までのアクセスエラーが発生しない。
フェイルオーバープログラム(haMgr)
フェイルオーバープログラムhaMgr
は独立したプロセスのプログラムです。(参考:haMgrリファレンス)
haMgr
がTHNRから呼び出し可能な(パス内に存在する)場合に限り、フェイルオーバーを実行します。
そうでない場合は、アプリケーションには単にネットワークエラーが返されます。
フェイルオーバープロセスは最初に開始したクライアントのみが行うことができます。 後から試みたクライアントはサーバーのHAオブジェクトをロックできずに失敗します。
失敗したクライアントはすぐにTHNRによって再度名前解決を開始します。 その際、フェイルオーバー中でないかを確認するため、HAオブジェクトのロックを最大60秒間試みます。 フェイルオーバーが完了しロックが開放されれば、新しい構成のホスト名が取得されます。
最小限のダウンタイム
以上の仕組みによって、マスターがダウンしても新しいマスターに自動でフェイルオーバーし、ダウンタイムなしに処理を継続することが可能です。 フェイルオーバーにかかる時間はスレーブの台数にもよりますが、検出に数秒、切替は1秒以下です。
また、実際のクライアントが直接死活監視を行うことで、検出とフェイルオーバープログラムの起動までの間にエラーを発生することがありません。 このため、マスターダウンで失敗するトランザクションは、ダウン時に既に開始されていたものだけになります。
THAは、意図的にマスターを切り替えるスイッチオーバーもサポートします。 スイッチオーバーの場合、現マスターでのトランザクションの終了を待って切替を行うので、何のデータも失うことはありません。
THAを構築する
THAを構築する手順を説明します。例では以下のサーバー構成と仮定します。
サーバー | IPアドレス |
---|---|
マスター | 192.168.0.2 |
スレーブ1 | 192.168.0.3 |
スレーブ2 | 192.168.0.4 |
-
MySQL5.6/MariaDB 10.0以上のサーバーを使い、単一マスターと複数スレーブでレプリケーションを構成します。 参考:MySQL/MariaDB GTID レプリケーション詳細
このとき、Transactdアクセスのためのユーザー名・パスワード、レプリケーションのためのチャンネル・ユーザー名・パスワード・オプションなどはすべてのサーバーで同じものが使用できるようにします。
-
すべてのサーバーの
my.cnf
にreport-host=192.168.0.x
のように、自身のホスト名もしくはIPアドレスを明示します。 8610以外のポートを使用している場合はreport-host=192.168.0.x:8611
のようにポート番号まで指定します。このホスト名は後述する
start
関数やhealth_check
などでも使用されます。 -
マスターサーバーの起動オプションに
–transactd-startup_ha=1
を加えて、マスターとして起動し直します。 -
Transactdクライアントアプリケーションから呼び出せる(パスの通った)ディレクトリに
haMgr
を配置します。 -
haMgr
の-c health_check
コマンドを使ってフェイルオーバー可能な状態かテストします。./haMgr64 -c health_check -o 192.168.0.2 -s 192.168.0.3,192.168.0.4 -u root -p abcd 2016-07-05T18:34:28 Starting health check... SLAVE_LIST=192.168.0.3,192.168.0.4 192.168.0.2: Role = Master OK! 192.168.0.2: HA lock OK! 192.168.0.3: Role = Slave OK! 192.168.0.3: Failover is disabled NG! 192.168.0.3: HA lock OK! 192.168.0.3: channel name= 192.168.0.3: SQL thread running OK! 192.168.0.3: IO thread running OK! 192.168.0.3: SQL thread delay=0 192.168.0.4: Role = Slave OK! 192.168.0.4: Failover is disabled NG! 192.168.0.4: HA lock OK! 192.168.0.4: channel name= 192.168.0.4: SQL thread running OK! 192.168.0.4: IO thread running OK! 192.168.0.4: SQL thread delay=0 2 errors detected. 2016-07-05T18:34:29 Done!
2か所
Failover is disabled NG!
という問題を検出しますが、この時点ではそのままOKです。後で自動フェイルオーバーを有効にします。 -
Transactdクライアントアプリケーションの先頭に、THNRの
start
関数の呼び出しを追加します。haNameResolver::start("master_host", "slave_host", "192.168.0.2,192.168.0.3,192.168.0.4", 1, "root", "abcd");
この関数の詳細はhaNameResolverを参照してください。
-
クライアントアプリケーションの中で、実ホスト名を指定していた部分を仮想ホスト名に置換します。
/* Access to the master */ db->open("tdap://root@master_host/db/test?pwd=abcd"); /* Access to the slave */ db->open("tdap://root@slave_host/db/test?pwd=abcd");
-
アプリケーションの動作チェックが済んで、正常に稼働することが確認できたら、
haMgr
を使って自動フェイルオーバーを有効にします。./haMgr64 -c set_failover_enable -v 1 -o 192.168.0.2 2016-07-06T10:21:04 Done!
transactd-startup_ha
オプションは、サーバー起動時のロールを設定します。
transactd-startup_ha=0
を指定した場合やmy.cnf
に指定がない場合、そのサーバーはスレーブとして起動します。transactd-startup_ha=1
を指定した場合、そのサーバーはマスターとして起動します。
haMgr
やAPI呼び出しを使用することで、サーバーを再起動せずにロールを指定することも可能です。
スイッチオーバーなどでマスターを切替えた後でサーバーを再起動すると、マスターは切替えられているにも関わらず、この起動オプションに従ったロールでサーバーが起動してしまいます。
起動時に前回終了時のロールを復元したい場合は、transactd-startup_ha
の値に4
を足します。
transactd-startup_ha=4
を指定した場合、前回終了時の情報があればそれに従ったロールで、なければスレーブとして起動します。transactd-startup_ha=5
を指定した場合、前回終了時の情報があればそれに従ったロールで、なければマスターとして起動します。
ただし、障害でダウンしたマスターサーバーは、前回終了時のロールをマスターとして記憶しているため、修復後に起動するにはtransactd-startup_ha=0
を指定し、スレーブとして明示する必要があります。
transactd-startup_ha
の値はdataフォルダのtransactd_srv_master.info
ファイルに保存されます。
このファイルを削除すると復元は無効になります。
THAを使用するアプリケーションの注意点
同一スレッドの2つのdatabaseオブジェクトとトランザクション
同じサーバーに対する2つのdatabase
オブジェクトインスタンスDB_A
とDB_B
を使用しているとします。
まずDB_A
でトランザクションを開始し、そのトランザクション内でDB_B
を使用した際にエラーが発生したとします。
このときDB_A
とDB_B
が同じスレッドで使用された場合は、DB_B
でのエラーをトリガーとした再接続は行われません。
DB_B
で再接続するにはDB_A
のトランザクション終了を待つ必要がありますが、それらが同じスレッドだとそれ以上処理が進まず永久にトランザクションが終了しないためです。
THAの管理
健全性の維持
高可用運用を実現するには、異常時に正しくフェイルオーバーが行われるかどうか日ごろから確認しておく必要があります。
THAの管理プログラムhaMgr
にはhealth_check
機能があり、フェイルオーバーが問題なく行えるかどうかテストできます。
スケジューラ等で定期的にテストすることでTHAの健全性を維持するこができます。参照:ヘルスチェック
ヘルスチェックでは、repl_user
とusername
で示されるアカウントの有効性についてはチェックされません。
これらのアカウントが問題なくCHANGE MASTER TO
などのオペレーションを実行する権限を有するかどうか、別途テストを行ってください。
フェイルオーバーが行われたかどうかの確認
THNRによって自動フェイルオーバーが行われた場合、MySQLのerror.log
(Windowsではイベントログ)にCHANGE MASTER TO ...
とマスタ切替の内容が記録されます。この記録を監視することでフェイルオーバーが行われたかどうかを知ることができます。
フェイルオーバー処理の詳細なログ
THNRによる自動フェイルオーバーの詳細な記録は、クライアントのログに記録されます。(THNRによってhaMgr
が実行された場合は、出力はエラーログにリダイレクトされます。haMgr
を直接ユーザーが起動した場合はコンソールに出力されます。)
具体的には以下のように記録されます。参照:エラーログ
2016-07-07T09:29:33 Starting fail over...
SLAVE_LIST=192.168.0.2,192.168.0.3,192.168.0.4
HP6730B:8611: promote to master
HP6730B:8611: channel name=
HP6730B:8611: set role=MASTER
HP6730B:8612: channel name=
HP6730B:8612: stop slave all
HP6730B:8612: change master to new master, pos=slave_pos
HP6730B:8612: start slave
2016-07-07T09:29:33 Done!
Transactd ClientとSQLアクセスの両方を使用するアプリケーションでのTHA
THAは、Transactd APIのみを使用したアプリケーションでは、最高のHA性能を発揮します。 高可用運用が最大の課題であるならば、アプリケーションをそのように変更することをお勧めします。
THA構成は、SQLからのアクセスに弊害を与えることはありません。Transactd APIには親和的に、SQLアクセスには透過的に働きます。 両方のアクセスが必要な場合は、THAの構成要素のどれを組み合わせるかによって複数の選択肢があります。ここでは主な選択肢を説明します。
THAを主体に構成する
これまで説明したTHAをその通りに構成します。SQLからのアクセスの際、マスターホスト名を haNameResolver::master()、スレーブホスト名を haNameResolver::slave()を使って取得しアクセスを行うようにします。 これで通常の動作は何も問題ありません。
問題があるのは、マスターの障害発生後、最初にアクセスするのがSQLであった場合です。 Transactd APIであれば自動で障害検出とフェイルオーバーや再名前解決などが行われ、最小限のエラーで回復します。 しかし障害発生後の最初のアクセスがSQLであった場合は、それらが行われずそのままエラーになります。 次のTransactd APIアクセスがあるまで障害の回復が行われません。
この点に関しては、アプリケーションに「SQLでのアクセスエラーがあった際にTransactd APIでのアクセスを行う」処理を追加することで、回復を早めることが可能です。
自動フェイルオーバーを使わない場合は、この構成はベストな選択肢です。 マスターの障害発生後、手動でスイッチオーバーすればよいソリューションでは何の問題もなくこの構成で使用できます。 その場合は、自動フェイルオーバーを無効にしておきます。
./haMgr64 -c set_failover_enable -v 0 -o 192.168.0.2
障害発生後の最初のアクセスとは、クライアントのプロセス単位です。1つのクライアントプロセスはTHNRをすべてのスレッドで共有します。
従来よりあるMySQLのHA構成を使用する
従来のMySQLのHAは、以下のように構成されます。
heartbeat
などによる障害検出mysqlfaileover
プログラムによるフェイルオーバーVirtualIP
によるホストアドレスの変更- ルータのARPキャッシュ更新
この構成の場合、アプリケーションでクライアントの再接続機能を有効にして、フェイルオーバー後新しいサーバーに再接続できるようにします。
/* アプリケーションの先頭で */
nsdatabase::setEnableAutoReconnect(true);
この構成の問題は、以下のようなものがあります。
- 障害発生からフェイルオーバーが完了するまでの間のアクセスはすべてエラーになる。
- スイッチオーバーでは、Transactdによるトランザクションの終了を待たないため、トランザクションがエラーになることがある。
- IPアドレスの変更、ARPの更新などOSや他の機器をコントロールするためそれらの構成に依存する。
従来よりあるMySQLのHA構成を主体にフェイルオーバーにhaMgrを使用する
フェイルオーバープログラムにhaMgr
を使用すると、スイッチオーバーの際にTransactdによるトランザクションが実行されていた場合、その終了を待機するためエラーにならないメリットがあります。
haMgrリファレンス
haMgr
はTHAをコントロールするためのプログラムです。以下の処理を行うことができます。
- スイッチオーバーの実行
- フェイルオーバーの実行
- マスターの降格処理(マスターからスレーブに変更)
- フェイルオーバーの有効/無効切替
- サーバーのロール変更
- 構成のヘルスチェック
コマンドラインパラメータ
command line option:
-c [ --command ] command [switchover | failover | demote_to_slave | set_failover_enable | set_server_role | health_check]
-o [ --cur_master ] current master host name
-n [ --new_master ] new master host name
-C [ --channel ] new master channel name
-P [ --repl_port ] new master port
-r [ --repl_user ] new master repl user
-d [ --repl_passwd ] new master repl password
-O [ --repl_option ] option params for change master(ex:MASTER_CONNECT_RETRY=30)
-s [ --slaves ] slave list for failover
-a [ --portmap ] port map ex:3307:8611
-v [ --value ] value (For set_failover_enable or set_server_role)
-u [ --username ] transactd username
-p [ --password ] transactd password
-R [ --readonly ] 0 | 1: When it is 1, the READONLY variable will be set ON to slaves and OFF to a master
-D [ --disable_demote ] 0 | 1: disable old master demote
-command
実行するコマンドを指定します。-cur_master
現在のマスターを指定します。-new_master
スイッチオーバーの際に新しくマスターにするサーバーを指定します。-channel
スイッチオーバーの際に新しいマスターに接続するためのチャンネル名を指定します。 指定しなければ、デフォルトの""
です。MySQL 5.7/MariaDB 10.0以上で有効です。MySQL5.6では無視されます。-repl_port
CHANGE MASTER TO
コマンドで使用するレプリケーションのポート番号を指定します。-repl_user
レプリケーションに使用するユーザー名を指定します。-repl_passwd
repl_user
に対するパスワードを指定します。-repl_option
CHANGE MASTER TO
コマンドの追加のオプションを指定します。 例:MASTER_CONNECT_RETRY=30
。複数ある場合はカンマで区切って指定します。-slaves
フェイルオーバーのための、現在のスレーブサーバー名をカンマで区切って指定します。-portmap
TransactdのポートとMySQLのポートの双方を変更している場合にその関連を指定します。例:-a 3307:8611
-value
set_failover_enable
コマンドとset_server_role
コマンドで設定する値を指定します。-username
Transactdへアクセスするためのユーザー名を指定します。-password
username
に対するパスワードを指定します。-readonly
0
または1
を指定します。 スイッチオーバーまたはフェイルオーバーの際にサーバーのREADONLY
変数の制御をする場合に1
を指定します。 マスターはOFFに、スレーブはONに設定されます。READONLY
変数はSQLアクセスについてのみ機能します。READONLY
変数はTransactd APIからのアクセスには何の制限も与えません。-disable_demote
0
または1
を指定します。 スイッチオーバーの際に旧マスターをスレーブに降格せずに、サーバー群から切り離す場合には1
を指定します。
スイッチオーバー
マスターを切り替えます。
例:マスターを192.168.0.2
から192.168.0.3
に切り替える。
./haMgr64 -c switchover -o 192.168.0.2 -n 192.168.0.3 -R1 -r replication_user -d abcd -u root -p xxxx
スイッチオーバーは、マスターを切り替えると同時に、旧マスターをスレーブに降格させます。
–disable_demote 1
を指定した場合は、旧マスターをスレーブに降格せずに、サーバー群から切り離します。–readonly 1
を指定した場合は、旧マスターにREADONLY
が設定され、SQLからのアクセスは読み取りのみ可能になります。
フェイルオーバー
フェイルオーバーを手動で実行します。
例:現在のスレーブが192.168.0.3
と192.168.0.4
の2台の状態でフェイルオーバーを実行する。
./haMgr64 -c failover -s 192.168.0.3,192.168.0.4 -u root -p xxxx
マスターの降格
例:ダウンした旧マスター192.168.0.2
の修復が完了したので、192.168.0.3
のスレーブに加える。
./haMgr64 -c demote_to_slave -o 192.168.0.2 -n 192.168.0.3 -r replication_user -d abcd -u root -p xxxx
フェイルオーバーの有効/無効切替
フェイルオーバーの有効/無効を切り替えます。値には、有効化は1
、無効化は0
を指定します。
例:現在のマスターサーバーは192.168.0.3
で、フェイルオーバーを有効化する。
./haMgr64 -c set_failover_enable -v 1 -o 192.168.0.3 -u root -p xxxx
サーバーのロール変更
サーバーのロールを変更します。値には、マスターには1
、スレーブには0
を指定します。
例:192.168.0.3
のロールをマスターにする。
./haMgr64 -c set_server_role -o 192.168.0.3 -v 1 -u root -p xxxx
構成のヘルスチェック
ヘルスチェックでは、マスターとマスターに接続しているすべてのスレーブのレプリケーションの状態・THAのためのサーバーロール・ロック可否・フェイルオーバーの有効/無効を確認して標準出力にレポートします。
プログラムの戻り値は、正常な場合は0
、エラーがある場合は1
が返されます。
例:マスターが192.168.0.2
で、スレーブが192.168.0.3
と192.168.0.4
の2台の状態で、ヘルスチェックを行う。
./haMgr64 -c health_check -o 192.168.0.2 -s 192.168.0.3,192.168.0.4 -u root -p xxxx
2016-07-05T18:34:28 Starting health check...
SLAVE_LIST=192.168.0.3,192.168.0.4
192.168.0.2: Role = Master OK!
192.168.0.2: HA lock OK!
192.168.0.3: Role = Slave OK!
192.168.0.3: Failover is enabled OK!
192.168.0.3: HA lock OK!
192.168.0.3: channel name=
192.168.0.3: SQL thread running OK!
192.168.0.3: IO thread running OK!
192.168.0.3: SQL thread delay=0
192.168.0.4: Role = Slave OK!
192.168.0.4: Failover is enabled OK!
192.168.0.4: HA lock OK!
192.168.0.4: channel name=
192.168.0.4: SQL thread running OK!
192.168.0.4: IO thread running OK!
192.168.0.4: SQL thread delay=0
No errors detected.
2016-07-05T18:34:29 Done!
ヘルスチェックでは、障害時に正しくフェイルオーバーできるかどうかを確認できます。 これを定期的に行うことで信頼性を高めることができます。
正しくヘルスチェックを行うには、パラメータの値に haNameResolver::start() と同じものを渡すことが重要です。