k8s_redis_sentinel_java_app_2
クバネティス(Kubernetes) 環境で Redis-Sentinel Java App 構築 ②
Failover テスト
🖧 Redis-Sentinel ポッド(Pod) ダイアグラム: Redis-0 Master
1. Failover(障害対応) テスト開始
SSH ターミナルを 2つ開き、Terminal-1 では App ポッド(Pod) 生成、Redis ポッド(Pod) ダウンなどを実行し、 Terminal-2 で App ログを見ます。
Java(Spring) App ポッド(Pod) 生成
サーバ (Terminal-1 [~/kube/app/sentinel]) で実行
$ kubectl apply -f app-deployment.yaml -> ポッド(Pod) 生成
💻 App ログ
サーバ (Terminal-2 [~/kube/app/sentinel]) で実行
$ kubectl logs -f -l app=spring-redis-sentinel-app
1秒あたり 10件ずつ入力([SUCCESS]) されることを確認できます。
💥 1. Redis(Redis-0) ポッド(Pod) ダウン
Terminal-1) $ date; kubectl delete pod redis-0 -> 15:47:39
💻 Redis-0 LOG
① 39秒 Redis ダウン (+0秒)
② 41秒 Redis 再起動 (+2秒)
③ 54秒 マスター -> レプリカへ切替 (+15秒)
Redis-0 全ログ
💻 Redis-1 LOG
① 43秒 レプリカ -> マスターへ切替 (+4秒)
App ログ
Terminal-2) $ kubectl logs -f -l app=spring-redis-sentinel-app
① 39秒 Redis 接続切断 -> 再接続試行 (+0秒)
② 44秒 入力失敗 1件発生: keyA-00000147 (+5秒)
③ 45秒から入力成功 (+6秒)
App 全ログ
🖧 Redis-Sentinel ポッド(Pod) ダイアグラム: Failover 状態 (Redis-1 Master)
2. Failback(原状復帰) テスト
1) Redis(Redis-1) ポッド(Pod) 💥ダウン(delete)
Terminal-1) $ date; kubectl delete pod redis-1 -> 15:48:05
💻 Redis-1 ログ
① 05秒 Redis ダウン (+0秒)
② 08秒 Redis 再起動 (+3秒)
③ 20秒 マスター -> レプリカへ切替 (+15秒)
💻 Redis-0 ログ
① 09秒 レプリカ -> マスターへ切替 (+4秒)
💻 App ログ
① 06秒 Redis-1 接続切断 -> 再接続試行 (+1秒)
② 10秒 入力成功(09秒に Redis-0 がマスターへ切り替わりました) (+5秒)
App 全ログ
🖧 Redis-Sentinel ポッド(Pod) ダイアグラム: 原状復帰状態 (Redis-0 Master)
🧑💻 テスト検討および核心要約
今回の障害対応(Failover/Failback) テストで、クバネティス(Kubernetes) 環境の Redis-Sentinel と Java(Spring Boot) アプリケーション間の実際の連動動作を検証しました。
⏱️ 障害対応タイムライン (Timeline)
| 区分 | 時刻 (相対時間) |
Redis-Sentinel 動作 | Java (Spring) App 動作 |
|---|---|---|---|
| 障害発生 | 15:47:39 (+0秒) |
Master(Redis-0) ポッド(Pod) 終了 (delete) | 接続切断検知および再接続試行 (Reconnecting) |
| Failover | 15:47:43 (+4秒) |
Sentinel が障害検知後 Redis-1 を Master へ昇格 | Sentinel から新規 Master IP を受信 |
| 復旧完了 | 15:47:45 (+6秒) |
新規 Master(Redis-1) データ書き込み準備完了 | [SUCCESS] 正常書き込み再開 (ただし 1件のリクエストは再試行処理) |
| 旧マスター再起動 | 15:47:54 (+15秒) |
再起動した Redis-0 が Redis-1 の Replica へ昇格/連動 | 影響なし (正常サービス維持) |
💡 実務適用のための核心示唆 (Key Takeaways)
-
1. Sentinel Failover 切替時間 (約 4~5秒):
マスターポッド(Pod) がダウンしたあと、Sentinel がダウンを判定(down-after-milliseconds 3000)し、投票(Quorum) を経て新しいマスターを昇格させるまで 約 4秒のダウンタイムが発生します。 -
2. Spring/Lettuce クライアント再試行(Retry) の重要性:
今回のテストでデータ損失がほとんどなかった核心理由は、App 側の再試行(Retry 5回 / 5秒) 設定のおかげです。 マスター切替中に発生した 1件の失敗リクエスト(keyA-00000147) も、バックグラウンド再試行で新規マスターへ渡り、無中断に近いサービス連続性を確保しました。 -
3. ユーザー体験(UX) およびタイムアウト考慮事項:
クライアント観点では、障害発生時に約 4~5秒の応答遅延(Latency) が発生します。 Web/App フロントエンド API 呼び出し時にユーザー画面が止まらないよう、Front-end Timeout および Circuit Breaker(Resilience4j など) を適切に組み合わせることを推奨します。 -
4. Automatic Failback(原状復帰) 未サポートおよび正常動作の特性:
既存 Master(Redis-0) が再び生きても、元の Master 位置へ復帰(Failback) せず、新規 Master(Redis-1) の Replica に入るのが Sentinel の正常な動作です。 (テスト 2回目の Failback は Redis-1 を強制削除して再誘導した結果です。)
🛡️ Front-end Timeout および Circuit Breaker 説明
🛡️ Redis 障害時にシステム麻痺を防ぐ安全装置
Sentinel の障害対応(Failover) 中に発生する 4~5秒の応答遅延(Latency) は、バックエンドサーバと ユーザー画面へ障害が伝播する連鎖障害(Cascading Failure) を引き起こすことがあります。 これを防ぐため、実務では次の 2つの安全装置を必ず組み合わせて構築します。
1. Front-end Timeout (フロントエンドタイムアウト)
ユーザーのブラウザやモバイルアプリがバックエンド API を呼んだあと、「応答が来ないときに無期限に待たず、リクエストを諦める最大時間」です。
- 問題状況 (Timeout 未設定時): Redis 障害中に 4秒間応答が止まると、焦ったユーザーが '再読み込み' や 'ボタン' を連打します。これによりバックエンド Tomcat/Spring スレッド(Thread) が枯渇し、Web サーバ全体がダウンします。
- 解決策 (2~3秒 Timeout 適用): 2秒以内に応答がなければ直ちにリクエストを中断し、「一時的なネットワーク遅延です。しばらくしてから再試行してください」 という案内を出してバックエンド暴走を遮断します。
2. Circuit Breaker (サーキットブレーカー - Resilience4j)
電気配電盤の '遮断器' のようにバックエンド(Spring) アプリケーション内部に置き、Redis 障害検知時に 遮断器を開いて(Open) Redis への接続試行を直ちに中断するライブラリです。
- 🟢 CLOSED (正常): すべてのキャッシュ/データリクエストを Redis へ正常に渡します。
- 🔴 OPEN (遮断): Redis 遅延/エラー率が指定値を超えると遮断器を開き、 Redis 呼び出しをそもそも試みず、あらかじめ準備した代替ロジック(Fallback: 例: Main RDB 直接照会) を 直ちに実行します。
- 🟡 HALF-OPEN (検証): Redis が復旧したか確認するため少数のリクエストだけ送り、 正常動作が確認できれば再び 🟢 CLOSED 状態へ戻します。
🔄 障害発生時の 2つの技術の協調プロセス
- 0秒 (Redis Master ダウン): Sentinel が Failover を開始し、応答遅延が発生
- 1~2秒 (Circuit Breaker 作動): Spring App の Resilience4j がエラー/遅延を検知し、遮断器を 🔴 OPEN へ切替 ➔ Redis の代わりに RDB を照会するかデフォルト値を返す(Fallback)
- 2秒 (Front-end Timeout 作動): フロントエンドがリクエストを安全に切り、無限ローディングおよびユーザー連打による WAS 暴走を防止
- 4~5秒 (Failover 完了 & 自動復旧): Sentinel が新規 Master 昇格を完了すると、Resilience4j がそれを検知して 🟢 CLOSED に戻し、キャッシュサービスを自動正常化
| << K8s Redis-Sentinel App ① | K8s Sidecarパターン 準備 ① >> |
|---|
