Amazon ElastiCache for Valkeyのdurabilityの効果を実際にフェイルオーバーを起こして検証してみた

Amazon ElastiCache for Valkeyのdurabilityの効果を実際にフェイルオーバーを起こして検証してみた

2026.06.04

こんにちは。サービス開発室の武田です。

2026年6月2日、Amazon ElastiCache for Valkeyがdurability(永続性)をサポートしました。Multi-AZのトランザクションログにデータを永続化することで、キャッシュでありながら「データが消えない」という選択肢が増えたアップデートです。

機能の概要、sync/asyncの2つのオプション、制限事項、パフォーマンス特性については、すでに大栗がまとめています。全体像はこちらをご覧ください。

https://dev.classmethod.jp/articles/amazon-elasticache-valkey-durability/

今回はその先、つまり「ACKされた書き込みは、フェイルオーバーが起きても本当に消えないのか」を確かめます。書き込み中のクラスターにフェイルオーバーを起こし、OK応答を受け取った書き込みを1件ずつ照合します。合わせて、アプリケーションから見た書き込み停止時間や、sync ⇔ asyncのオンライン切り替えの挙動も検証します。

検証の設計

durabilityの価値は「ACKされた書き込みは障害が起きても消えない」ことに尽きます。これを確認するため、次のように検証を設計しました。

  1. 連番付きキーを毎秒約100件のペースで書き込み続ける
  2. 書き込み中にtest-failover APIでフェイルオーバーを発生させる
  3. クライアントが OK応答を受け取った(ACK済みの)書き込みだけ を記録しておく
  4. フェイルオーバー完了後、ACK済みの全キーをプライマリから読み取り、欠落がないか照合する

ポイントは3です。タイムアウトや接続エラーになった書き込みは「ACKされていない」ので照合対象から外します。durabilityが保証するのはあくまでACK済みの書き込みだからです。

なお、この検証で確認できるのは「test-failoverによる計画的フェイルオーバー条件下で欠落しないこと」です。AZ障害や複数同時障害まで含めた証明ではありません。とはいえ、従来のElastiCacheではこの条件でも直近の書き込みが消え得たので、違いを確かめる意味は十分あります。

検証環境

項目 内容
クラスター cache.m6g.large × 2(1シャード、プライマリ + レプリカ)、Valkey 9.0、durability sync
配置 プライマリ: ap-northeast-1a / レプリカ: ap-northeast-1c(東京リージョン)
クライアント EC2 t4g.micro(Amazon Linux 2023)、valkey-cli 9.0.4、redis-py 7.0.1

ノードタイプは、durability対応ファミリー(R7g / R6g / M7g / M6g / C7gn)のうち最安のcache.m6g.largeを選びました。syncはノード料金に18%の追加料金がかかり、2ノードで約$0.36/時間(東京リージョン、2026年6月3日時点)です。

クラスター作成はCLIで

コンソールでの作成手順は大栗の記事にあるので、こちらはCLIで作成します。create-replication-group--durability syncを付けるだけです。

1点だけ前提があります。--durabilityパラメーターは発表と同時にリリースされた次のバージョン以降でないと使えません。

  • AWS CLI v2: 2.34.59以降
  • AWS CLI v1: 1.45.20以降
  • botocore: 1.43.20以降

手元のCLIが古いとUnknown options: --durabilityになるので、先にアップデートしておきます。

aws elasticache create-replication-group \
  --replication-group-id valkey-durability-test \
  --replication-group-description "Valkey durability sync test" \
  --engine valkey \
  --engine-version 9.0 \
  --cache-node-type cache.m6g.large \
  --num-node-groups 1 \
  --replicas-per-node-group 1 \
  --cluster-mode enabled \
  --multi-az-enabled \
  --automatic-failover-enabled \
  --transit-encryption-enabled \
  --cache-subnet-group-name valkey-durability-test-subnet \
  --security-group-ids sg-xxxxxxxxxxxxxxxxx \
  --durability sync

レスポンスには要求値のDurabilityと実効値のEffectiveDurabilityが含まれます。作成完了まで約18分でした。

{
    "ReplicationGroup": {
        "ReplicationGroupId": "valkey-durability-test",
        "Status": "creating",
        "Engine": "valkey",
        "Durability": "sync",
        "EffectiveDurability": "sync"
    }
}

ちなみに作成後、INFO persistenceを見るとaof_enabled:0でした。エンジン側のAOF(Append Only File)は使われていません。durabilityはValkeyエンジンの外側、ElastiCacheのインフラ側のMulti-AZトランザクションログで実現されていることが分かります。

検証1: フェイルオーバーでACK済みの書き込みは残るか

本題です。検証クライアント(redis-pyのクラスターモード + TLS)で連番キーを書き込み続けながら、フェイルオーバーを実行します。

aws elasticache test-failover \
  --replication-group-id valkey-durability-test \
  --node-group-id 0001

イベントログを見ると、フェイルオーバー自体は約19秒で完了しています。

04:04:22 UTC | Test Failover API called for node group 0001
04:04:41 UTC | Failover to replica node valkey-durability-test-0001-002 completed

フェイルオーバー完了後、ACK済みの全キーを新しいプライマリから読み取って照合した結果がこちらです。

項目 結果
ACK済み書き込み 9,342件
フェイルオーバー後に欠落していたキー 0件
値が壊れていたキー 0件

ACK済みの書き込みは1件も失われませんでした。

この検証はクライアント実装を変えて2回実施しており、2回目はACK済み20,303件に対して欠落ゼロでした。合計すると、2回のフェイルオーバーでACK済み書き込み29,645件、欠落0件です。

検証2: フェイルオーバー中、アプリケーションの書き込みは何秒止まるか

データが消えないことは分かりました。次に気になるのは「フェイルオーバー中、アプリケーションはどれくらい書き込めなくなるのか」です。エラー時に再接続するロジックを入れたクライアントで計測しました。

結果のタイムラインです(フェイルオーバーAPI実行時刻を0秒とする)。

時刻 イベント
-76秒 書き込み開始(正常に書き込み続ける)
+3.5秒 最初の接続エラー(旧プライマリがシャットダウンされ接続拒否)
+21.0秒 書き込み回復(新プライマリへの接続確立)
項目 結果
書き込み試行 20,331件
ACK成功 20,303件(99.86%)
エラー 28件
アプリケーションから見た書き込み停止時間 約17.5秒

書き込みが止まるのは約17.5秒で、イベントログ上のフェイルオーバー所要時間(約17秒)とほぼ一致します。この間のエラーはわずか28件で、再接続後は元どおり書き込みが続きました。

クライアント実装で復帰時間は大きく変わる

実は1回目の検証では、雑な再接続ロジックのクライアントを使っていたため、フェイルオーバー後に クライアントが復帰できない 状態になりました。クラスタートポロジーの変更にクライアントが追従できなかったためです。

クライアント実装 フェイルオーバー後の挙動
リトライ無効 + 接続エラー時のみ再接続 復帰できず、エラーが出続けた
どのエラーでも再接続 17.5秒で自動復帰

もうひとつ注意点があります。test-failover完了イベントの後も、旧プライマリがレプリカとしてクラスターに再参加するまで時間がかかります(今回の検証では約7分)。この間、AWS APIのステータスはavailableに戻っていても、当該ノードはエンジンレベルでcluster_state:failを返します。そのため、全ノードの正常性を前提にするクライアント初期化(redis-pyrequire_full_coverage=Trueなど)は失敗します。

サーバー側がdurabilityでデータを守ってくれても、アプリケーションが復帰できなければ意味がありません。クラスターモード対応クライアントの再接続・リトライ設定は必ず確認しておきましょう。

検証3: sync ⇔ asyncのオンライン切り替え

durabilityの有効/無効は作成後に変更できませんが、syncとasyncの切り替えは可能です。切り替え中に何が起きるのか確かめました。

aws elasticache modify-replication-group \
  --replication-group-id valkey-durability-test \
  --durability async \
  --apply-immediately

切り替え中、30秒ごとにステータス確認と書き込みを行った結果です。

  • EffectiveDurabilityがsyncからasyncに変わるまで 約50秒
  • 切り替え中もクラスターのステータスはavailableのまま
  • 切り替え中も書き込みは成功し続けた(ダウンタイムなし)

modify直後のレスポンスではEffectiveDurability: syncのままで、少し遅れてasyncに切り替わります。要求値(Durability)と実効値(EffectiveDurability)が分かれているのはこのためです。

アプリケーションを停止せずにオンラインで切り替えられるので、「まずsyncで運用してみて、書き込みレイテンシー要件が厳しければasyncに落とす」という運用ができます。

参考までに、同一条件(同時接続10、value 100バイト、TLS)でのvalkey-benchmarkの結果も載せておきます。クライアントがt4g.microなので絶対値は参考程度に見てください。

SET(書き込み) sync async
p50 3.29ms 0.26ms
p99 4.40ms 0.52ms
GET(読み取り) sync async
p50 0.22ms 0.25ms
p99 0.42ms 0.50ms

書き込みはsyncで約12倍のレイテンシー(それでも1桁ミリ秒)、読み取りはsync/asyncで差なし、という公式の説明どおりの結果でした。

CloudWatchメトリクスの実値

durableクラスター向けに追加された2つのメトリクスも確認しました。

メトリクス 内容 検証中の値
DurabilityLag ACK済みだがまだ永続化されていない最古の書き込みの経過時間 0ms(syncは書き込み時点で永続化済みのため常に0)
DurabilityBufferExceededErrorCount 10秒バッファ超過による書き込み拒否回数 0

asyncで運用する場合は、DurabilityLagが10,000ms(10秒)に近付いていないかを監視しておきましょう。10秒に達するとプライマリは新しい書き込みを拒否し始めます。また書き込みトラフィックがトランザクションログのスループットを超えると、TrafficManagementActiveメトリクスが1を出力します。

この機能で守れるもの・守れないもの

「障害でデータが消えない」ことは確認できました。ただし、durabilityはバックアップの代替ではありません。最後に整理しておきます。

守れるもの

  • ノード障害・フェイルオーバー・再起動時のデータ
  • syncならACK済みの書き込みすべて。asyncの場合、ACK済みでも未永続化(最大10秒分)の書き込みは失われ得る

守れないもの

  • 誤ったDELETEやFLUSHALL(論理削除はそのまま実行される)
  • TTL切れによる期限削除、maxmemory超過時のeviction(durabilityは障害時のデータ保護機能であり、これらは仕様どおりの削除として実行される)
  • アプリケーションのバグによるデータ破壊
  • リージョン障害(Multi-AZであってマルチリージョンではない)

「キーが絶対に消えない」機能ではなく、「障害でデータが失われない」機能です。「間違って消した」に備えるには、従来どおりスナップショット(バックアップ)の併用が必要です。

まとめ

検証結果をまとめます。

  • ACK済み書き込みは、フェイルオーバーを起こしても1件も失われなかった(2回の検証で計29,645件、欠落ゼロ)
  • フェイルオーバーは約17〜19秒で完了し、適切に実装されたクライアントなら約17.5秒で書き込みが復帰する
  • 雑な再接続実装では、クライアントの復帰に失敗する場合がある。リトライ設定の確認は必須
  • syncとasyncはオンラインで切り替え可能(約50秒、ダウンタイムなし)

「ACKされた書き込みは消えない」という公式の説明を、実際にフェイルオーバーを起こして確認できました。マイクロ秒の読み取りと永続性の両方が欲しいデータ、たとえばAIエージェントのメモリやセッションステートには、有力な選択肢になります。

どなたかの参考になりましたら幸いです。

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事