はじめに
こんにちは。インフラエンジニアの平田です。 IT 基盤部に所属し、全世界向けのゲームタイトルのインフラ運用を担当しています。
今回は、マネージドのインメモリキャッシューサービスである Amazon ElastiCache for Redis
(以降 ElastiCache) と Google Cloud Memorystore for Redis
(以降 Memorystore) のそれぞれについて、スペック変更時 (バージョンのグレードアップ、及びノードタイプ・メモリサイズの変更時) のダウンタイム 1 について調査しました。本記事では、その結果についてご紹介いたします。
背景
我々のグループでは複数のゲームタイトルを AWS や GCP で運用しており、かねてより ElastiCache と Memorystore の両方を運用しています。
運用している ElastiCache 及び Memorystore のうち、一部は バージョン 3.X で運用しています。しかし、ElastiCache のバージョン 3.X の EOL 日が 2023 年 7 月 31 日 であることを受け、バージョン 3.X で稼働している ElastiCache のバージョンを 6.X に上げることにしました。 そして Memorystore についても、今後の EOL に備えて、並行してバージョンを 6.X に上げることにしました。
またバージョンアップと並行し、一部のインスタンスについては、スペック適正化のためノードタイプ及びメモリサイズの見直しを並行して実施することにしました。
バージョンの変更、及びノードタイプ・メモリサイズの変更を行うにあたり、ダウンタイムがどの程度発生するのかは、サービスへの影響の程度を確認するため事前に調査する必要があります。 特にダウンタイムの発生期間が長く、それが許容できない場合は、サービスをメンテナンス状態に入れて作業をする必要があります。
そこで今回は、ElastiCache と Memorystore それぞれにおいて、下記項目におけるダウンタイムを計測しました。
- バージョンの変更 (3.X → 6.X)
- ノードタイプ・メモリサイズの変更
また ElastiCache と Memorystore で可能な限り条件を統一して比較検証を行い、それぞれの検証項目における結果の差異を調査しました。
検証環境
本検証は、以下の環境で実施しました。
ElastiCache | Memorystore | |
---|---|---|
リージョン | 東京リージョン (ap-northeast-1) | 東京リージョン (asia-northeast1) |
ノードタイプ / メモリサイズ |
・cache.t3.small (2 vCPU, 1.37 GiB) ・cache.t3.medium (2 vCPU, 3.09 GiB) ・cache.m5.large (2 vCPU, 6.38 GiB) |
・1GiB ・3GiB ・6GiB |
構成 | ・プライマリノード/レプリカノード 1台ずつ ・マルチ AZ は有効にする ・クラスターモードはオフにする (※1) |
・プライマリノード 1 台 (※2) ・スタンダードティアを使用 (※2) |
(※1) クラスターモードをオンにすると、データのパーティション分割・水平スケーリングが可能になる (参考: ElastiCache > レプリケーション: Redis (クラスターモードが無効) 対 Redis (クラスターモードが有効) )。今回は使用しない。
(※2) 一見 ElastiCache の条件と一致しないように見えるが、スタンダードティアを使用することで、ゾーン間のレプリケーションが有効になる。今回はこの条件で ElastiCache とほぼ同等な構成として扱うことにする (参考: Memorystore > Redis の階層の機能 )。 なお、参照専用のリードレプリカは、Redis バージョン 5.0 以降でないと有効にできない。
検証項目・手順
検証項目
前述の通り、本検証は「バージョンの変更 (3.X → 6.X)」、「ノードタイプ・メモリサイズの変更」の 2 つのオペレーションにおけるダウンタイムを計測しました。 具体的な検証項目は以下の通りで、各項目ごとに 3 回 計測を実施しました。
バージョンの変更
構築した ElastiCache へ変更を施し、バージョン 3.2 から 6.2 へアップグレードを実施しました。そのアップグレード中に確認されたダウンタイムを計測しました。ノードタイプは cache.t3.small、cache.t3.medium、cache.m5.large の3つを選定しました 2。Memorystore も同様に、メモリサイズ 1 GiB、3 GiB、6 GiB の3つを選定し、バージョン 3.2 から 6.X へのアップグレード時のダウンタイムを計測しました。
ノードタイプ・メモリサイズ の変更
ElastiCache / Memorystore 共に、各 redis バージョンにおいて、異なるノードタイプ (もしくはメモリサイズ) 間でそれぞれスケールアップ・スケールダウンを実施し、その時のダウンタイムを計測しました。
各 2 つのオペレーションについては、下記公式ドキュメントにしたがって実行しました。
- ElastiCache > エンジンバージョンのアップグレード
- ElastiCache > レプリカを含む Redis クラスターのスケールアップ
- Memorystore > インスタンスの Redis バージョンのアップグレード
- Memorystore > Redis インスタンスをスケーリングする
事前準備
今回の検証では、実際に我々の開発環境での使用状況を想定して、下記スクリプトを用いて各データベース (計 16 個 3) にそれぞれ 1000 件のデータをインサートしてから検証を行いました。
# 対象の redis のエンドポイントを指定
ENDPOINT='PRIMARY_ENDPOINT_HERE'
# データのインサート
for d in `seq 0 15`;
do
for i in `seq 1 1000`;
do
redis-cli -h $ENDPOINT -n $d SET db$d_key$i db$d_value$i;
done;
done
ダウンタイム測定
今回の検証では、プライマリーエンドポイントへの書き込みを行い、その後読み込みを行います。この一連の流れを 1 秒毎に繰り返しました。実行は以下のスクリプトを用いて行い、発生したダウンタイムを計測しました。
# count の初期値とエンドポイントの値を代入
count=1
ENDPOINT='PRIMARY_ENDPOINT_HERE'
# 計測コマンド
while true
do
echo `date` `redis-cli -h ${ENDPOINT} -n 0 set "key_$count" "value_$count"`;
sleep 0.5;
echo `date` `redis-cli -h ${ENDPOINT} -n 0 get "key_$count"`;
count=`expr $count + 1`;
sleep 0.5;
done
検証結果
以下が検証結果となります。各 3 回の検証結果を、スラッシュ (/
) 区切りでまとめました。
バージョンアップグレード (3.X -> 6.X) 時
今回の検証では、ElastiCache のバージョンアップグレード時はダウンタイムが殆ど発生しないという結果になりました。 なお AWS 公式ドキュメント には、5.0.5 以前のバージョンでバージョンアップをする際は、30 秒から 1 分程度のフェイルオーバーが発生する可能性があると記載されています。
実際にアップグレードをする際は、最悪の場合 1 分程度のダウンタイムが発生することを許容できるか確認する必要はありますが、そのような 1 分程度のダウンタイムは頻繁には発生しないことが期待できそうです。
Memorystore に関しては、redis-cli の応答が 16 秒程度返って来ず、書き込みも読み込みもできない状態が見受けられました。 GCP 公式ドキュメント にも記載されていますが、Memorystore のバージョンアップグレード中に、Redis ノードに対しての接続がリセットされます。この影響で一時的に redis-cli の応答がない期間が発生するのではと考えられます。
### redis-cli を用いたダウンタイム計測中のログ
... (省略) ...
Wed Dec 28 14:01:27 UTC 2022 OK
Wed Dec 28 14:01:27 UTC 2022 value_672
Wed Dec 28 14:01:28 UTC 2022 OK # <--- ここから 約16秒間、redis-cli による読み込みの応答が返ってこない
Wed Dec 28 14:01:44 UTC 2022 value_673
Wed Dec 28 14:01:44 UTC 2022 OK
Wed Dec 28 14:01:45 UTC 2022 value_674
... (省略) ...
よって Memorystore でバージョンアップする際は、十数秒程度書き込みや読み込みができない状態が許容できるか確認する必要があると明らかになりました。
なお ElastiCache / Memorystore ともに、異なるノードタイプやメモリサイズ間でダウンタイム時間に有意な差がないことも検証結果から確認できました。
ノードタイプ・メモリサイズの変更時
ElastiCache
Memorystore
Memorystore のメモリサイズ変更時は、先ほどと同様に、約 16 秒 redis-cli が応答しない期間が発生しました。 これはバージョン変更時と同様、 スケーリング中も Redis ノードに対しての接続がリセットされる ので、その影響ではないかと考えられます。
ElatiCache のノードタイプ変更時について、 本検証では全 48 回の試行を実施しましたが、内 30 試行で 15 秒未満のダウンタイムという結果が得られました。 半分以上のケースで Memorystore よりも短いダウンタイム期間となっていますが、ケースによっては 20 秒以上のダウンタイムが発生する場合もありました (本検証では 2 試行でそれぞれ 20 秒、24 秒のダウンタイムが発生)。 検証より、ElastiCache のノードタイプを変更する際は、20 秒程度のダウンタイムが許容できるか確認しなければならないことが分かりました。
なお今回の検証においては、ElastiCache のダウンタイム期間中は、Memorystore のように redis-cli が応答しない期間は確認できませんでした。 読み込み専用の slave に対して書き込みを行おうとし、エラーが返されていました。 したがって、特に書き込みが頻繁に行われる場合においては、20 秒程度の書き込みができないことを許容できるか確認してから、ノードタイプの変更を行う必要があると明らかになりました。
### redis-cli を用いたダウンタイム計測中のログ
... (省略) ...
Thu Dec 22 14:01:19 UTC 2022 OK
Thu Dec 22 14:01:20 UTC 2022 value_458
Thu Dec 22 14:01:20 UTC 2022 READONLY You can't write against a read only slave.
Thu Dec 22 14:01:21 UTC 2022
Thu Dec 22 14:01:21 UTC 2022 READONLY You can't write against a read only slave.
Thu Dec 22 14:01:22 UTC 2022
Thu Dec 22 14:01:22 UTC 2022 READONLY You can't write against a read only slave.
Thu Dec 22 14:01:23 UTC 2022
Thu Dec 22 14:01:23 UTC 2022 READONLY You can't write against a read only slave.
Thu Dec 22 14:01:24 UTC 2022
Thu Dec 22 14:01:24 UTC 2022 READONLY You can't write against a read only slave.
... (省略) ...
まとめ
今回の検証によって、以下の結果が得られました。
- ElastiCache のバージョンアップ時のダウンタイムは Memorystore より短く、ダウンタイムを発生させずにバージョンアップ可能であることが期待できる。
- ElastiCache / Memorystore ともに、異なるノードタイプやメモリサイズ間において、バージョンアップ時のダウンタイム時間に有意な差がない。
- ノードタイプ・メモリサイズの変更時については、Memorystore は 16 秒程度のダウンタイムが発生する。ElastiCache は、最大 20 秒以上のダウンタイムが発生する場合がある。
なお本検証は、可能な限り条件を一致させて検証結果を比較をしましたが、完全に条件を一致させて比較を行ったわけではないので、本結果が ElastiCache と Memorystore の優劣を一意に決定できるものではないことにご留意ください。
今後 ElastiCache、Memorystore ともに品質が更に向上し、これまで以上に運用しやすいマネージドサービスになることを願っています。
付録: (ElastiCache) プライマリノード 1 台での検証結果
前述の検証では、ElastiCache はプライマリノードとレプリカノードそれぞれ 1 台ずつという構成で検証を行いましたが、 レプリカノードを使用せず、プライマリノード 1 台のみという構成でも検証してみました。
その構成においてノードタイプを変更した際に、redis-cli の結果からは書き込みが完了しているように見えるが、実際には書き込めていない期間が数秒程度存在するケースが散見されました。
プライマリノード 1 台構成で ElastiCache を本番運用しているサービスは少ないかもしれませんが、もしその構成で今後ノードタイプを変更する際は、上記事象が許容できるかどうかを確認する必要があると明らかになりました。
### redis-cli を用いたダウンタイム計測中のログ
Tue Jan 10 06:17:52 UTC 2023 OK
Tue Jan 10 06:17:52 UTC 2023 value_412
Tue Jan 10 06:17:53 UTC 2023 OK
Tue Jan 10 06:17:53 UTC 2023 value_413
Tue Jan 10 06:17:54 UTC 2023 OK # <-- 書き込みができているように見える
Tue Jan 10 06:17:54 UTC 2023 value_414
Tue Jan 10 06:17:55 UTC 2023 OK
Tue Jan 10 06:17:55 UTC 2023 value_415
Tue Jan 10 06:17:56 UTC 2023 OK
... (省略) ...
Tue Jan 10 06:18:09 UTC 2023 OK
Tue Jan 10 06:18:10 UTC 2023 value_429
Tue Jan 10 06:18:10 UTC 2023 OK
Tue Jan 10 06:18:11 UTC 2023 value_430
Tue Jan 10 06:18:11 UTC 2023 OK
### 実際の redis のデータ
$ for i in `seq 1 450`; do redis-cli -h $ENDPOINT -n 0 GET key_$i; done
... (省略) ...
"value_411"
"value_412"
"value_413"
(nil) # <-- 値が入っていない...
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
"value_429"
"value_430"
... (省略) ...
-
本検証においては 「読み込み・書き込みのいずれかができなかった期間」をダウンタイムとみなします。 すなわち、読み込みも書き込みもできない期間、読み込みはできるが書き込みできない期間はダウンタイムとみなします。 これは読み込み・書き込みの両方が成立しないと、 Redis として正常な運用が出来ないためです。 ↩︎
-
本検証では異なるメモリサイズで比較することを重要視しているため、バーストパフォーマンスインスタンス (cache.t3.small、cache.t3.medium) と非バーストパフォーマンスインスタンス (cache.m5.large) が混在することを許容しています。 ↩︎
-
redis 3.2 及び redis 6.2 の databases のデフォルト値が 16 であるため、今回は 16 個のデータベースを使用しました。 ↩︎
最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。