わずか数秒!RDS Proxy を Aurora 高速フェイルオーバーに利用する

RDS Proxy を利用したフェイルオーバーの優位性に着目してみました
2020.08.25

RDS Proxy が GA されたことは記憶に新しいですが、割と「あぁ、Lambda でコネクション問題を解決してくれるやつでしょ?」というイメージが強いので、Lambda などのサーバーレスアーキテクチャを使われていない環境だとあまり注目されてなかったりするでしょうか?

今回は Lambda やコネクション数の課題がない環境でも、RDS Proxy を使うことで簡単に Aurora 高速フェイルオーバーを実装できるんで恩恵ありますよ!という検証を行ったのでご紹介したいと思います。

そもそも RDS Proxy とは

RDS Proxy はその名前のとおり、RDS 向けの DB プロキシです。よく言われるメリットは冒頭で申し上げたとおり Lambda -> RDS のように従来はコネクション数の問題でアンチパターンと言われた構成において、プロキシで RDS へのコネクションを集約することで課題がクリアになるというものです。

このあたりの詳細は岩田の記事を参照いただくのが良いかと思います。

さて、ここからコネクションの集約ではなく、今回の本題である「フェイルオーバー」のメリットにフォーカスしてお伝えしたいと思います。

Aurora 高速フェイルオーバーについて

Aurora は従来の RDS と比較すると随分と早くフェイルオーバーできる印象があるかと思います。公式の情報によればレプリカが構成されている場合、通常 30 秒以内に完了します。

Q: フェイルオーバー中はどのようなことが起き、どのくらいの時間がかかりますか?
A: Amazon Aurora レプリカを同一の、または異なるアベイラビリティーゾーンに作成しておくと、フェイルオーバーが発生した場合、Aurora は DB インスタンスの正規名レコード (CNAME) を切り替えて正常なレプリカを指定します。指定されたレプリカはこれにより新しいプライマリに昇格します。フェイルオーバーは開始から終了まで通常 30 秒以内に完了します。

(引用元:Amazon Aurora のよくある質問

とはいえ、早い・遅いの認識は提供しているサービスによって異なります。30 秒のダウンタイムでも遅いとされる環境においては数秒でフェイルオーバーしてほしい場合もあります。そのようなときに Aurora では高速フェイルオーバーを利用します。

従来の高速フェイルオーバーと課題

Aurora MySQL の場合、高速フェイルオーバーを実現させる仕組みとしてグローバル変数 innodb_read_only があります。この innodb_read_only を利用した高速フェイルオーバー方法としては、概ね以下の 2 パターンです。( Aurora PostgreSQL は、また別の仕組みで高速フェイルオーバーを実現します )

ドライバー対応の課題

クライアント側のドライバーで対応するメリットは追加リソースが必要ないことです。しかし、クライアントが増えるほどに運用とメンテナンスの負荷は高くなります(修正アップデートの対応など)。そのため、フェイルオーバー高速化のための実装をクライアント側に任せることに抵抗を感じるかたも少なくないかも知れません。

DB プロキシ対応の課題

DB プロキシで対応するメリットはクライアント側に手をいれる必要がないことです。基本的に参照先を DNS で管理できていれば、CNAME レコードをプロキシに向けることで切り替えが可能です。

一方で DB プロキシとなるインスタンスが必要となりますので、追加コストが発生します。さらにプロキシが単一障害点とならないように可用性、拡張性、モニタリングなどをユーザー側で管理する必要があります。

(引用元:オープンソースプラットフォームで ProxySQL を使用して、Amazon Aurora クラスターでの SQL の読み取りと書き込みを分割する方法

アプリケーションサーバーに DB プロキシを相乗りさせて利用することも出来ますが、そうなると「クライアント側のメンテナンスが発生する」という点で、先述のドライバーによる対応と同じ課題が出てきます。

そこで RDS Proxy

RDS Proxy は先述の例でいうと「DB プロキシ対応」に該当しますが、課題であるユーザー管理の部分をまるっとマネージドサービスにお任せすることで課題がクリアになります。

料金

追加コストが発生する点は避けられませんが、基になる DB インスタンスの vCPU あたり $0.018/h です。仮に db.r5.large(2 vCPU) のプロキシとして利用する場合、30 日換算で $12.96 です。DB プロキシの運用から開放されることを踏まえて、安い・高いを判断いただくのが良いでしょう。

やってみる

それでは早速、クラスターエンドポイントと RDS Proxy を利用した場合のフェイルオーバー時間を比較してみましょう。

今回の環境

今回は以下の環境で検証しています。

  • 東京リージョン
  • Aurora
    • db.r5.large(レプリカを 2 台追加した 3 台構成)
    • 5.7.mysql_aurora.2.08.1
  • クライアント
    • Amazon Linux 2
    • m5.large
    • SQL クライアントは以下のとおり
$ mysql --version
mysql  Ver 15.1 Distrib 5.5.64-MariaDB, for Linux (x86_64) using readline 5.1

SQL クライアント側では TTL の最小化などのチューニングは一切行っておらず yum install mariadb でインストールしただけの状態で利用しています。

RDS Proxy は以下の記事を参考に作成済みです。

計測方法

Proxy SQLの記事を参考に、以下のスクリプトを実行中に手動フェイルオーバーを実行します。

tess.sh

#! /bin/bash

while true
do
  DATETIME=$(date "+%Y-%m-%d %T.%N")
  (echo "select '${DATETIME}', now(3), @@hostname, @@innodb_read_only;" | mysql -udbuser -pdbpassword -h 各エンドポイント -s) &
  sleep 0.5
done

以下のようなレスポンスが返ります。最終フィールドが innodb_read_only になっており 0writer1 ならば reader という判断になります。

2020-08-25 04:28:42.194083284 2020-08-25 04:28:42.211 ip-10-7-2-92  0

フェイルオーバー時間

フェイルオーバーによる切断開始から、再度 writer ノードからの応答が安定(継続的に innodb_read_only = 0 から応答)したタイミングまでをフェイルオーバー時間としています。

計測結果

5 回のフェイルオーバーテストによる実測値は以下のとおりです。sleep が 0.5 秒なので、ざっくり計測である点はご了承ください。平均値をとるのに 5 回では少ないと思いますので、あくまで参考値程度にお考えください。

リーダーエンドポイントついては、フェイルオーバー直後は writerreader が入り混じって応答がありましたので、ひとまず writer でもレスポンスが返ってきた時間と、reader からの応答が安定(継続的に innodb_read_only = 1 から応答)したタイミングを括弧( )の時間で記載しています。

対象 1回目 2回目 3回目 4回目 5回目 平均値
クラスターエンドポイント(秒) 48.0 15.0 15.0 11.0 9.0 19.6
RDS Proxy(秒) 0.5 0.5 1.5 1.5 2.0 1.2
リーダーエンドポイント(秒) 8.0
(50.0)
6.5
(42.0)
10.0
(51.0)
11.5
(305.0}
8.0
(54.0)
8.8
(100.4)

RDS Proxy への接続ログ

1回目、2回目は 0.5 秒としていますが、sleep が 0.5 だと切れ目なく接続できてしまったので、実際には 0.5 未満 ということですね。

$ ./test.sh
(中略)
2020-08-25 04:28:42.194083284	2020-08-25 04:28:42.211	ip-10-7-2-92	0
2020-08-25 04:28:42.696020168	2020-08-25 04:28:42.737	ip-10-7-2-92	0
2020-08-25 04:28:43.197867170	2020-08-25 04:28:44.272	ip-10-7-1-87	0 <-- ここで切り替わっている
2020-08-25 04:28:43.699713439	2020-08-25 04:28:44.273	ip-10-7-1-87	0
2020-08-25 04:28:44.201673281	2020-08-25 04:28:44.728	ip-10-7-1-87	0

クラスターエンドポイントへの接続ログ

クラスターエンドポイントの場合、概ね 10 秒以内に再接続されるものの、切り替え直後は writerreader を返すようで、ふらふらと安定しません。先の表では、このふらふらが落ち着いた最初の時間をフェイルオーバー完了時間として記載しています。

2020-08-25 04:28:41.977532219	2020-08-25 04:28:41.997	ip-10-7-2-92	0
2020-08-25 04:28:42.479412087	2020-08-25 04:28:42.496	ip-10-7-2-92	0
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 104
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'database.cluster-czaiwhovvutn.ap-northeast-1.rds.amazonaws.com' (111)
2020-08-25 04:28:49.505833236	2020-08-25 04:28:49.521	ip-10-7-1-87	0
2020-08-25 04:28:50.007785756	2020-08-25 04:28:50.055	ip-10-7-1-87	0
2020-08-25 04:28:50.509662450	2020-08-25 04:28:50.550	ip-10-7-1-87	0
2020-08-25 04:28:51.011514856	2020-08-25 04:28:51.018	ip-10-7-1-87	0
2020-08-25 04:28:51.513480124	2020-08-25 04:28:51.529	ip-10-7-1-87	0
2020-08-25 04:28:52.015351001	2020-08-25 04:28:52.022	ip-10-7-1-87	0
2020-08-25 04:28:52.517243413	2020-08-25 04:28:52.532	ip-10-7-1-87	0
2020-08-25 04:28:53.019198023	2020-08-25 04:28:53.037	ip-10-7-2-92	1
2020-08-25 04:28:53.521108088	2020-08-25 04:28:53.545	ip-10-7-2-92	1
2020-08-25 04:28:54.022979099	2020-08-25 04:28:54.041	ip-10-7-2-92	1
2020-08-25 04:28:54.524963681	2020-08-25 04:28:54.544	ip-10-7-2-92	1
2020-08-25 04:28:55.026832836	2020-08-25 04:28:55.043	ip-10-7-2-92	1
2020-08-25 04:28:55.528693775	2020-08-25 04:28:55.544	ip-10-7-2-92	1
2020-08-25 04:28:56.030545625	2020-08-25 04:28:56.049	ip-10-7-1-87	0
2020-08-25 04:28:56.532439063	2020-08-25 04:28:56.577	ip-10-7-1-87	0
2020-08-25 04:28:57.034317461	2020-08-25 04:28:57.051	ip-10-7-2-92	1
2020-08-25 04:28:57.536183575	2020-08-25 04:28:57.554	ip-10-7-2-92	1

このようにして見ると RDS Proxy のフェイルオーバーが本当にキレイで優秀であることがわかります。

RDS Proxy の注意点

「RDS Proxy えぇやん!」

と思っていただけたならば幸いです。

が、制約事項もございますのであらかじめご確認のうえでご検討ください。以下、一例を記載しています。詳細はリンクを参照ください。

サポートエンジン

RDS Proxy に対応している DB エンジンは Aurora を含めて MySQLPostgreSQL のみです。

  • MySQL は 5.6, 5.7 をサポート(8.0 は非対応)
  • PostgreSQL は 10,11,11.5 をサポート

writer へのアクセスのみ

RDS Proxy を介したアクセスは writer インスタンスで処理されます。執筆時点においてリーダーエンドポイントはサポートされていませんので、read 中心のアクセスはリーダーエンドポイントを直接利用してください。

RDS Proxy の listen ポートは固定

RDS Proxy の listen ポートは MySQL: 3306, PostgreSQL: 5432 固定です

さいごに

RDS Proxy は Lambda などにおけるコネクション数問題の救世主的に語られがちで、「サーバーレス使ってないんで興味ないすわ」とスルーされていた方も少なくないのではないでしょうか。

今回、コネクション数以外の観点で RDS Proxy の有用性をご紹介したく、高速フェイルオーバーを取りあげました。従来だと高速フェイルオーバーの導入はちょと面倒でしたが、RDS Proxy を利用することで非常に簡単に実装できます。

もし、Aurora のフェイルオーバー時間短縮にお悩みであれば、ご検討されてみてはいかがでしょうか。

そして、「めっちゃ便利なので、是非、リーダーエンドポイントのサポートも!!何卒、なにとぞっ!」と AWS さんにフィードバックを!(個人の感想です)

以上!大阪オフィスの丸毛(@marumo1981)でした!

あわせて読みたい