Amazon Auroraの障害テストを試してみた。

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんばんは、城内です。
最近、3歳半になる娘が『ちいさなプリンセス ソフィア』を観るようになって、急に妙なリーダーシップを発揮するようになりました。
両親共にそんな気質は持ち合わせていないので、どんな成長を遂げるのかちょっと不安です。。

といったどうでもいいプライベートな近況報告を織り交ぜながら、引き続き先日東京リージョンに上陸したAmazon Auroraを触っていきたいと思います。

はじめに

今回は、Auroraの障害テストを実施してみたいと思います。Auroraでシミュレーションできる障害は以下の4つです。

  • インスタンスのクラッシュ
  • レプリカの障害
  • ディスクの障害
  • ディスクの輻輳

上記の内、インスタンスとレプリカ、ディスクの障害テストを試してみたいと思います。
(ディスクの輻輳は、ディスクの障害をやるからまいっか的なノリで外しましたw)

試してみる

では、早速1つずつどんな挙動をするか確認していきたいと思います。
手順は以下のドキュメントを参考にしています。

環境は、testdbデータベースにsampleテーブルを作成し、適当な値のデータを200万レコードくらい入れてあります。

インスタンスのクラッシュ

インスタンスのクラッシュは、ALTER SYSTEM CRASH障害挿入クエリを使用します。
オプションが、INSTANCEDISPATCHERNODEと3つあるので、それぞれの挙動を確認しました。

まずは、INSTANCEです。

mysql> ALTER SYSTEM CRASH INSTANCE;
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql> 
mysql> select * from sample where id between '1' and '10';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
ERROR 2003 (HY000): Can't connect to MySQL server on 'cl-tokyo-aurora.cluster-abcdef123456.ap-northeast-1.rds.amazonaws.com' (111)
ERROR:
Can't connect to the server

...

mysql> select * from sample where id between '1' and '10';
No connection. Trying to reconnect...
Connection id:    2
Current database: testdb

+----+----------+--------------------------------+-------+---------------------+
| id | name     | description                    | price | created_at          |
+----+----------+--------------------------------+-------+---------------------+
|  1 | product1 | 9d1f7acd1c74f8ecc8e213ed41170c |   317 | 2014-04-13 17:38:56 |
|  2 | product2 | ae894317ec7484c0c1c600e2a1159a |  6870 | 2014-04-01 10:24:20 |
|  3 | product3 | d899f84d362ec59848489d233648c3 |   553 | 2014-02-17 03:32:41 |
|  4 | product4 | 43328ca2ff593895a04ffa642e9ff5 |  3091 | 2014-05-06 13:01:56 |
|  6 | product6 | 391314984430f929e9e40cac153009 |  5356 | 2014-05-21 06:55:28 |
|  7 | product7 | c63f9ef07b1cf909aa3124ac1d926c |  6619 | 2014-06-29 23:28:39 |
|  8 | product8 | 63b09a7e54b97f6cdcb44aa3176d53 |  6298 | 2014-03-16 03:52:38 |
|  9 | product9 | 7ba7518e69e438eeb4fc8ea40c725a |  4016 | 2014-02-20 04:13:03 |
+----+----------+--------------------------------+-------+---------------------+
8 rows in set (0.00 sec)

mysql> 

SQLを発行した直後に接続が切られ、すぐには再接続できませんでした。再接続できるまでは、体感で3秒程度だったかと思います。

イベントとしては、以下のように出力されています。

rds_01-r1

接続先はクラスターエンドポイントを使用しており、上図がレプリカ(Reader)に接続していた時で、下図はマスター(Writer)に接続していた時です。
マスターでインスタンス障害が発生したケースでは、マスターとレプリカの両方が再起動されています。
(ちなみに、それぞれ個別のエンドポイントに接続して試した際は、それぞれのインスタンスのみが再起動されていました)

rds_07-w1

次に、DISPATCHERです。

mysql> ALTER SYSTEM CRASH DISPATCHER;
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql> 
mysql> select * from sample where id between '1' and '10';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
ERROR 2003 (HY000): Can't connect to MySQL server on 'cl-tokyo-aurora.cluster-abcdef123456.ap-northeast-1.rds.amazonaws.com' (111)
ERROR:
Can't connect to the server

...

mysql> select * from sample where id between '1' and '10';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    3
Current database: testdb

+----+----------+--------------------------------+-------+---------------------+
| id | name     | description                    | price | created_at          |
+----+----------+--------------------------------+-------+---------------------+
|  1 | product1 | 9d1f7acd1c74f8ecc8e213ed41170c |   317 | 2014-04-13 17:38:56 |
|  2 | product2 | ae894317ec7484c0c1c600e2a1159a |  6870 | 2014-04-01 10:24:20 |
|  3 | product3 | d899f84d362ec59848489d233648c3 |   553 | 2014-02-17 03:32:41 |
|  4 | product4 | 43328ca2ff593895a04ffa642e9ff5 |  3091 | 2014-05-06 13:01:56 |
|  6 | product6 | 391314984430f929e9e40cac153009 |  5356 | 2014-05-21 06:55:28 |
|  7 | product7 | c63f9ef07b1cf909aa3124ac1d926c |  6619 | 2014-06-29 23:28:39 |
|  8 | product8 | 63b09a7e54b97f6cdcb44aa3176d53 |  6298 | 2014-03-16 03:52:38 |
|  9 | product9 | 7ba7518e69e438eeb4fc8ea40c725a |  4016 | 2014-02-20 04:13:03 |
+----+----------+--------------------------------+-------+---------------------+
8 rows in set (0.02 sec)

mysql>

こちらも同様に接続が切られましたが、再接続までの時間が少し長く、5秒くらいはかかった気がしました。

イベントは以下の通りで、こちらはマスターとレプリカで違いはありませんでした。

rds_02-r2

最後に、NODEです。

mysql> ALTER SYSTEM CRASH NODE;
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql> 
mysql> select * from sample where id between '1' and '10';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
ERROR 2003 (HY000): Can't connect to MySQL server on 'cl-tokyo-aurora.cluster-abcdef123456.ap-northeast-1.rds.amazonaws.com' (111)
ERROR:
Can't connect to the server

...

mysql> select * from sample where id between '1' and '10';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    3
Current database: testdb

+----+----------+--------------------------------+-------+---------------------+
| id | name     | description                    | price | created_at          |
+----+----------+--------------------------------+-------+---------------------+
|  1 | product1 | 9d1f7acd1c74f8ecc8e213ed41170c |   317 | 2014-04-13 17:38:56 |
|  2 | product2 | ae894317ec7484c0c1c600e2a1159a |  6870 | 2014-04-01 10:24:20 |
|  3 | product3 | d899f84d362ec59848489d233648c3 |   553 | 2014-02-17 03:32:41 |
|  4 | product4 | 43328ca2ff593895a04ffa642e9ff5 |  3091 | 2014-05-06 13:01:56 |
|  6 | product6 | 391314984430f929e9e40cac153009 |  5356 | 2014-05-21 06:55:28 |
|  7 | product7 | c63f9ef07b1cf909aa3124ac1d926c |  6619 | 2014-06-29 23:28:39 |
|  8 | product8 | 63b09a7e54b97f6cdcb44aa3176d53 |  6298 | 2014-03-16 03:52:38 |
|  9 | product9 | 7ba7518e69e438eeb4fc8ea40c725a |  4016 | 2014-02-20 04:13:03 |
+----+----------+--------------------------------+-------+---------------------+
8 rows in set (0.02 sec)

mysql>

こちらも接続が切られるのは他の2つと同様ですが、再接続までの時間が、接続先のレプリケーションロールによって2秒ほど違いがあった気がします(マスターが3秒、レプリカが5秒程度)。

イベントも以下の通り、マスターとレプリカで出力結果が異なりました(上がレプリカ、下がマスター)。

rds_03-r3

rds_09-w3

レプリカの障害

レプリカの障害は、ALTER SYSTEM SIMULATE READ REPLICA FAILURE障害挿入クエリを使用します。

1分間障害を発生させ、その間にマスター側でレコードの更新をかけてみます。

mysql> ALTER SYSTEM SIMULATE 100 PERCENT
    -> READ REPLICA FAILURE TO ALL
    -> FOR INTERVAL 1 MINUTE;
Query OK, 0 rows affected (0.00 sec)

mysql> system date
Sat Oct 10 08:28:11 UTC 2015
mysql> select * from sample where id = '1';
+----+----------+--------------------------------+-------+---------------------+
| id | name     | description                    | price | created_at          |
+----+----------+--------------------------------+-------+---------------------+
|  1 | product1 | dbeda3fc110a8d9e0e79175e46a97d |  3724 | 2014-02-28 11:58:12 |
+----+----------+--------------------------------+-------+---------------------+
1 row in set (0.00 sec)

mysql> UPDATE sample SET
    -> name = CONCAT('product', id),
    -> description = SUBSTRING(MD5(RAND()), 1, 30),
    -> price = CEIL(RAND() * 10000),
    -> created_at = ADDTIME(CONCAT_WS(' ','2014-01-01' + INTERVAL RAND() * 180 DAY, '00:00:00'), SEC_TO_TIME(FLOOR(0 + (RAND() * 86401))))
    -> where id = '1';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> system date
Sat Oct 10 08:28:19 UTC 2015
mysql> select * from sample where id = '1';
+----+----------+--------------------------------+-------+---------------------+
| id | name     | description                    | price | created_at          |
+----+----------+--------------------------------+-------+---------------------+
|  1 | product1 | 4e3bfa531e8cea1373a319a12885ba |  1254 | 2014-01-11 21:26:36 |
+----+----------+--------------------------------+-------+---------------------+
1 row in set (0.00 sec)

mysql>
mysql> system date
Sat Oct 10 08:28:23 UTC 2015
mysql> select * from sample where id = '1';
+----+----------+--------------------------------+-------+---------------------+
| id | name     | description                    | price | created_at          |
+----+----------+--------------------------------+-------+---------------------+
|  1 | product1 | dbeda3fc110a8d9e0e79175e46a97d |  3724 | 2014-02-28 11:58:12 |
+----+----------+--------------------------------+-------+---------------------+
1 row in set (0.00 sec)

mysql>
mysql> system date
select * from sample where id = '1';
Sat Oct 10 08:28:37 UTC 2015
mysql> select * from sample where id = '1';
+----+----------+--------------------------------+-------+---------------------+
| id | name     | description                    | price | created_at          |
+----+----------+--------------------------------+-------+---------------------+
|  1 | product1 | dbeda3fc110a8d9e0e79175e46a97d |  3724 | 2014-02-28 11:58:12 |
+----+----------+--------------------------------+-------+---------------------+
1 row in set (0.00 sec)

...

mysql> system date
Sat Oct 10 08:29:10 UTC 2015
mysql> select * from sample where id = '1';
+----+----------+--------------------------------+-------+---------------------+
| id | name     | description                    | price | created_at          |
+----+----------+--------------------------------+-------+---------------------+
|  1 | product1 | 4e3bfa531e8cea1373a319a12885ba |  1254 | 2014-01-11 21:26:36 |
+----+----------+--------------------------------+-------+---------------------+
1 row in set (0.01 sec)

mysql>

結果、レプリカにマスター側での更新が反映されるのは障害復旧後でした。
あくまで疑似的な障害なので、反映にかかる時間などは分かりませんが、復旧後は自動的にレプリカ側に差分が反映されることが分かりました。

ディスクの障害

ディスクの障害は、ALTER SYSTEM SIMULATE DISK FAILURE障害挿入クエリを使用します。

障害期間は1分で、その間にレコードの更新をかけてみます。

mysql> select * from sample where id = '1';
+----+----------+--------------------------------+-------+---------------------+
| id | name     | description                    | price | created_at          |
+----+----------+--------------------------------+-------+---------------------+
|  1 | product1 | 56013face92e631465e9fe3eee6d8c |  8475 | 2014-02-28 01:26:45 |
+----+----------+--------------------------------+-------+---------------------+
1 row in set (0.00 sec)

mysql>
mysql> ALTER SYSTEM SIMULATE 100 PERCENT DISK FAILURE FOR INTERVAL 1 MINUTE;
Query OK, 0 rows affected (0.00 sec)

mysql>
mysql> UPDATE sample SET
    -> name = CONCAT('product', id),
    -> description = SUBSTRING(MD5(RAND()), 1, 30),
    -> price = CEIL(RAND() * 10000),
    -> created_at = ADDTIME(CONCAT_WS(' ','2014-01-01' + INTERVAL RAND() * 180 DAY, '00:00:00'), SEC_TO_TIME(FLOOR(0 + (RAND() * 86401))))
    -> where id = '1';
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql>
mysql> select * from sample where id = '1';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    1
Current database: testdb

+----+----------+--------------------------------+-------+---------------------+
| id | name     | description                    | price | created_at          |
+----+----------+--------------------------------+-------+---------------------+
|  1 | product1 | 36fad9b847baff1e6f71e4bb6aebcc |  5177 | 2014-04-13 07:02:06 |
+----+----------+--------------------------------+-------+---------------------+
1 row in set (0.12 sec)

mysql>

結果は、障害発生中にUPDATEを実行したところ、接続が切られました。ただし、その後に再接続してみると、更新は反映されていました。
疑似的な障害だからかもしれませんが、実際の障害でも同様の挙動をするようであれば、更新は破棄されるのではなく、復旧後に自動反映されるということになりますね。
(※あくまで結果からの推測ですので、仕様とは限りません)

なお、1分間ディスク障害を発生させていたら、フェイルオーバーが発生し、レプリカがマスターに昇格していました。

rds_10

ちなみに、20秒で試した際には、フェイルオーバーは発生しませんでした。

さいごに

今回の検証では、実際に試してみて出た結果をそのまま記載しています。
意図としては、実は私の検証方法がいまいちで仕様通りの結果になっていなかったという可能性は否定できないかと思いましたので、あくまでドキュメントを参考に試してみた結果をそのままお伝えすることにしました。

試してみた感想としては、やはり対障害性は高いと感じたので、後はアプリ側でリトライ処理を組み込んでおけば、たいていの障害には耐えられるなと思いました。

うーん、すごいぞAurora!