RDSでリードレプリカの状態が監視可能になったので試してみた

2013.06.03

RDS - リードレプリカの状態を監視可能になりました

こんにちは植木和樹です。5月23日よりAWS RDSのMySQLでリードレプリカのレプリケーション状態が監視可能になりました。

 【AWS発表】 Amazon RDS - リードレプリカの状態を監視可能に

ということで試してみました。

マネージメントコンソールでレプリケーション状態を確認する

RDSインスタンスのページでリードレプリカを見ると"Replication State"という項目が追加されています。下の画面のように replicating になっていれば正常です。ところで、いつの間にやらRDSのインターフェースが新しくなっていますね。

20130601-replica-01

レプリケーションを失敗させてみよう

MySQLマスターサイトからリードレプリカを作成し、あとは気長に失敗するのを待って・・・いる時間はないので、無理矢理失敗させてしまいましょう。今回はリードレプリカのDBパラメータを「書き込み可能に」変更し、マスターとレプリカ間でデータ不整合を発生させてみました。リードレプリカを書き込み可能にするにはDBパラメータグループを変更(read_only=0)します。

まずはDBパラメータグループを作成します。

20130601-replica-02

DBパラメータグループ名を入力して作成します。

20130601-replica-03

作成したDBパラメータグループを選択し"Edit Parameters"をクリックします。

20130601-replica-04

この画面でもう一度"Edit Parameters"をクリック。

20130601-replica-05

read_onlyの値を”0”に変更します。

20130601-replica-06

ページ上部に戻り“Save Changes"で設定を保存します。

20130601-replica-07

この書き込み可能にしたDBパラメータをリードレプリカに割り当てます。DBインスタンスの画面でリードレプリカを選択し"Instance Actions"から"Modify"をクリックします。

20130601-replica-08

“Parameter Group"を変更します。設定を即時反映させたいので"Apply Immediately"にもチェックしておきましょう。

20130601-replica-09

20130601-replica-09

20130601-replica-11

レプリカに書き込み可能になったので、マスターとレプリカの間でデータ不整合を発生させます。まずはマスター側でテーブルを作成し、レコードを1件INSERTしてみます。

master> create table test(id int primary key, val varchar(8));
Query OK, 0 rows affected (0.09 sec)
master> insert into test values(1, 'aaaa');
Query OK, 1 row affected (0.02 sec)

master> select * from test;
+------+------+
| id   | val  |
+------+------+
|    1 | aaaa |
+------+------+
1 row in set (0.00 sec)

レプリカ側に接続してSELECTすると、正常にレコードが挿入されています。この時点ではレプリケーションは正常のようです。それではレプリカ側に id=2 のレコードをINSERTしましょう。

replica> select * from test;
+------+------+
| id   | val  |
+------+------+
|    1 | aaaa |
+------+------+
1 row in set (0.01 sec)

replica> insert into test values(2, 'cccc');
Query OK, 1 row affected (0.02 sec)

replica> select * from test;
+----+------+
| id | val  |
+----+------+
|  1 | aaaa |
|  2 | cccc |
+----+------+
2 rows in set (0.00 sec)

再度マスターに接続し、プライマリキーが重複したレコードをINSERTします。

master> insert into test values(2, 'bbbb');
Query OK, 1 row affected (0.01 sec)

master> select * from test;
+----+------+
| id | val  |
+----+------+
|  1 | aaaa |
|  2 | bbbb |
+----+------+
2 rows in set (0.00 sec)

レプリカに接続してレコードをSELECTします。

replica> select * from test;
+----+------+
| id | val  |
+----+------+
|  1 | aaaa |
|  2 | cccc |
+----+------+
2 rows in set (0.00 sec)

レプリカへの反映が失敗しました!!マスターにINSERTした"bbbb"の値が反映されていません。

レプリカ失敗を確認する

レプリケーションが失敗した状態でマネージメントコンソールを確認してみましょう。"Replication State"が error になり、"Replication Error"にエラー理由が表示されています。プライマリキーの重複エラーがでていることが分かります。

20130601-replica-12

実際の運用ではこの後レプリカ側の不整合を確認、対応(レプリカ側のレコードをDELETEするなど)します。不整合が解決すると自動的にレプリケーションは再開されます。

またはエラーを強制的に無視することもできます。レプリカ側で次のコマンドを実行すると「エラー状態」がリセットされレプリケーションが再開されます。

mysql> CALL mysql.rds_skip_repl_error;
+-------------------------------------+
| Message                             |
+-------------------------------------+
| Statement in error has been skipped |
+-------------------------------------+
1 row in set (0.02 sec)

+---------------------------+
| Message                   |
+---------------------------+
| Slave is running normally |
+---------------------------+
1 row in set (2.02 sec)

Query OK, 0 rows affected (2.02 sec)

コマンド実行後、しばらくするとマネージメントコンソールの表示が replicating に戻ります。

20130601-replica-15

レプリケーション失敗を通知する

レプリケーションエラーが起きた時にSNSで通知させることが可能です。通知設定は"Event Subscriptions"から行います。レプリケーションのエラーは"Souce-Type"が"db-instance"に含まれます。Amazon Relational Database Service User Guide

20130601-replica-13

レプリケーションエラーが起きるとSNSを通じて、以下のようなメールで通知されます。

20130601-replica-14

CloudWatchでレプリケーションの遅れ具合をみる

CloudWatchでレプリケーションの遅れをみることができます。aws-apitools-monパッケージがインストールされたEC2インスタンスから確認してみます。

$ mon-get-stats ReplicaLag \
  --start-time 2013-06-01T13:00:00.000 \
  --namespace "AWS/RDS" \
  --dimensions "DBInstanceIdentifier=replica" \
  --headers --show-table \
  --statistics "Maximum"

Time                 Maximum  Unit
2013-06-01 13:00:00  -1.0     Seconds
2013-06-01 13:01:00  -1.0     Seconds
2013-06-01 13:02:00  -1.0     Seconds
2013-06-01 13:03:00  -1.0     Seconds
2013-06-01 13:04:00  -1.0     Seconds
2013-06-01 13:05:00  -1.0     Seconds
2013-06-01 13:06:00  -1.0     Seconds
2013-06-01 13:07:00  -1.0     Seconds
2013-06-01 13:08:00  -1.0     Seconds
2013-06-01 13:09:00  -1.0     Seconds
2013-06-01 13:10:00  -1.0     Seconds
2013-06-01 13:11:00  -1.0     Seconds
2013-06-01 13:12:00  -1.0     Seconds
2013-06-01 13:13:00  -1.0     Seconds
2013-06-01 13:14:00  0.0      Seconds
2013-06-01 13:15:00  0.0      Seconds
2013-06-01 13:16:00  0.0      Seconds
2013-06-01 13:17:00  0.0      Seconds

エラーのまましばらく放置しておいても-1.0から値が変化しませんでした。どうやらレプリケーションの遅れ時間を表示しているわけではなく、遅れていればマイナスを、遅れていなければゼロを返すようです。

まとめ

リードレプリカはマスタサイトへ負荷を集中させないための負荷分散の仕組みですが、レプリケーションエラーでマスタからのデータ反映が止まってしまうとレプリカには最新データが渡りません。前日の実績を集計するためにレプリカに繋いで夜間バッチ処理を流したのに、レプリケーションエラーで途中までの前日実績データしか集計されていない!!となったら翌朝大問題です(あぁ・・・嫌な思い出が・・・)。今回のレプリカ状況監視の仕組みを使ってエラーは早期検知、対応できるようにしておきたいものです。