ElastiCache Redisのサービス更新時のダウンタイムを調査した

2021年6月24日

Amazon ElastiCache

稼働中の ElastiCache Redis にサービスの更新(engine-update)の通知があったので手動で適用をしました。メンテナンスのヘルプ - Amazon ElastiCache | AWS によると数秒のダウンタイムが発生するとのことですが、どのくらいサービスがダウンするのか redis-cli を使って調べてみたので記録を残します。

目次

  1. ElastiCache Redis の環境
  2. 検証用の環境
  3. サービス更新の様子
  4. 1 台目の書き込みコマンドのエラー停止
  5. 2 台目の書き込みコマンドはエラーなし
  6. フェイルオーバーのその後
  7. まとめ

ElastiCache Redis の環境

  • モード:Redis
  • ノードのタイプ:cache.t3.micro
  • エンジンのバージョン 互換性:6.0.5
  • シャード:1
  • ノードの数:2
  • マルチ AZ:enabled
  • 自動フェイルオーバー:enabled
  • データ量:およそ 50 MB

検証用の環境

  • Amazon ECS-optimized Amazon Linux 2 × 2 台
  • Docker 19.03.13-ce
  • redis:6.0.5-alpine Docker イメージ

1 台目

ターミナルウィンドウを 2 個立ち上げ、それぞれのウィンドウで 1 台目の Amazon Linux にログインし Docker コンテナにログインします。

docker run --rm -it redis:6.0.5-alpine ash

読み書きのコマンドを実行して、更新中にエラーが出るかどうかを確認します。

ウィンドウ 1 では、1 秒に 1 回、数字を 1 ずつ増やしながら書き込み。

redis-cli -h redis-primary-endpoint set mykey1 "1"
redis-cli -h redis-primary-endpoint -i 1 -r 3600 incr mykey1

ウィンドウ 2 では、1 秒に 1 回、上記で書き込んだキーを読み取り。

redis-cli -h redis-primary-endpoint -i 1 -r 3600 get mykey1

2 台目

ターミナルウィンドウを追加で 2 個立ち上げ、2 台目の Amazon Linux でコンテナにログインします。それぞれのウィンドウで以下のコマンドを実行します。

ウィンドウ 3 では、ループしながら 1 秒に 1 回、数字を 1 ずつ増やしながら別のキーに書き込み。

for i in $(seq 1 3600); do
  redis-cli -h redis-primary-endpoint set mykey2 ${i}
  sleep 1
done

ウィンドウ 4 では、ループしながら 1 秒に 1 回、上記のキーを読み取り。

while [ true ]; do
  redis-cli -h redis-primary-endpoint get mykey2
  sleep 1
done

サービス更新の様子

サービス更新をする前に前述の 4 個のスクリプトを流しておきます。

サービス更新を開始すると、サービスの更新ステータスの画面の「ステータスを更新」が waiting-to-start になります。

サービス更新ステータス

サービス更新ステータスのクラスター名のリンクをクリックすると、ノードの「ステータスを更新」が waiting-to-start になっているのも確認できます。

サービス更新ステータス

しばらくして、ノードの末尾 002 (レプリカ)が in-progress になりました。この後順番に見ていきますが、先にレプリカから更新が行われ、レプリカの更新後に自動でフェイルオーバーしてレプリカとプライマリが入れ替わります。

サービス更新ステータス

数分後、ノードの末尾 002 (レプリカ)が complete になりました。

サービス更新ステータス

さらに数分後、ノードの末尾 001 (プライマリ)が in-progress になりました。

サービス更新ステータス

クラスタのステータスも modifying になりました。更新が終わったレプリカをプライマリに昇格させる処理に入りました。

クラスターのステータス

1 台目の書き込みコマンドのエラー停止

この後、1 台目のターミナルウィンドウに変化が。書き込みをしているコマンドがエラーで止まりました。

/data # redis-cli -h redis-primary-endpoint -i 1 -r 3600 incr mykey1
(integer) 1
(integer) 2
...
(integer) 1296
(integer) 1297
(error) READONLY You can't write against a read only replica.
Error: Server closed the connection
/data # 

1 台目で読み込みをしているターミナルウィンドウは書き込みが止まった後 30 秒ほど 2797 の数字を表示し、その後エラーが表示され応答待ちの状態になりました。

/data # redis-cli -h redis-primary-endpoint -i 1 -r 3600 get mykey1
"1"
"2"
...
"1296"
"1297"
"1297"
... (30回ほど続く)
"1297"
"1297"
(error) LOADING Redis is loading the dataset in memory

エラーで止まったターミナルで、書き込みのコマンドを再実行。

/data # redis-cli -h redis-primary-endpoint -i 1 -r 3600 incr mykey1
(integer) 1298
(integer) 1299

応答待ちだった読み込みコマンドを実行していたターミナルは、しばらくして数字が飛んだ状態で再開しました。

/data # redis-cli -h redis-primary-endpoint -i 1 -r 3600 get mykey1
"1"
"2"
...
"1297"
"1297"
(error) LOADING Redis is loading the dataset in memory
"1324"
"1325"

2 台目の書き込みコマンドはエラーなし

2 台目の検証マシンで流していたコマンドはエラーを検出できませんでした。ダウンタイムが 1 秒より短かったのか、接続待ちの状態になっていたか、はっきりしません。コマンドの実行時間を出すようにしておけばよかったです。

for i in $(seq 1 3600); do
  redis-cli -h redis-primary-endpoint set mykey2 ${i}
  sleep 1
done

OK
OK
OK
while [ true ]; do
  redis-cli -h redis-primary-endpoint get mykey2
  sleep 1
done

"1296"
"1297"
"1299"
"1299"
"1301"

フェイルオーバーのその後

その後は特にエラーになることもなく「ステータスを更新」が complete になり、更新が完了しました。

サービス更新ステータス

クラスタのステータスも available になりました。

クラスターステータス

ノードのステータスも available です。末尾 002 が primary に、001 が replica になっていることも確認できます。

クラスターノードステータス

まとめ

  • 今回は準備不足でダウンタイムは計測できず
  • メンテナンスのヘルプ - Amazon ElastiCache | AWS ではダウンタイムは数秒と記載あり
  • 読み書きエラーは確認できたので、ダウンタイムがあるものとしてアプリケーション側で対処しておく必要あり

うまくダウンタイムを測ることができず、ハッキリしない結果になってしまいました。ただし書き込みでエラーは発生したので、ダウンタイムはあるものとして、アプリケーション側でエラーが起きても問題ない作りにしておく必要はありそうです。

またサービス更新の機会があったら再挑戦して記事を更新します。

-技術ブログ
-