リトライパターン

英語名 Retry Pattern
読み方 リトライ パターン
難易度
所要時間 実装に半日〜1日
提唱者 分散システム設計のベストプラクティス
目次

ひとことで言うと
#

ネットワークの一時的な不安定やサービスの瞬断など、一過性の障害に対して自動的にリクエストを再送し、人手の介入なしに処理を成功させるパターン。

押さえておきたい用語
#

押さえておきたい用語
指数バックオフ
リトライ間隔を指数的に増加させる戦略。1秒→2秒→4秒→8秒と間隔を広げる。
ジッター
バックオフにランダムな揺らぎを加えること。多数のクライアントが同時にリトライする「thundering herd」を防ぐ。
サーキットブレーカー
障害が続く場合にリクエスト送信自体を停止するパターン。リトライの上限を超えた後の保護手段。
一時的障害(Transient Fault)
ネットワーク瞬断やサーバーの一時的な過負荷など、時間が経てば自然に回復する障害。
デッドレターキュー
リトライ上限を超えても処理できなかったメッセージを退避させるキュー。後から手動で再処理できる。

リトライパターンの全体像
#

リトライ戦略とエスカレーションの流れ
エラー分類一時的: 503, タイムアウト永続的: 400, 401, 403429: 待機してリトライリトライ戦略指数バックオフ+ジッター最大3回、合計30秒以内冪等性キーで二重処理防止フォールバック上限超過→エラー通知キューへ退避サーキットブレーカー連携可視化リトライ率をメトリクスで監視頻発なら根本原因を追う
リトライ判断フロー
1
エラー分類
一時的か永続的かを判定
2
バックオフ
指数バックオフ+ジッターで待機
3
再試行
冪等性を確保してリトライ
4
上限判定
上限超過ならフォールバック実行

こんな悩みに効く
#

  • ネットワークの瞬断で処理が失敗し、ユーザーに手動リトライをさせてしまう
  • 外部APIが一時的にエラーを返すたびに、エラーログが大量発生して対応に追われる
  • 一時的な障害と永続的な障害を区別できず、不要なアラートが飛ぶ

基本の使い方
#

ステップ1: リトライ対象のエラーを分類する

すべてのエラーをリトライすべきではない。対象を見極める。

  • リトライすべき: ネットワークタイムアウト、HTTP 503、接続リセットなどの一時的障害
  • リトライすべきでない: HTTP 400(バリデーションエラー)、HTTP 401(認証エラー)などの永続的障害
  • HTTP 429(レートリミット)は待機時間を空けてリトライする

ポイント: 冪等でない操作(決済実行など)のリトライは特に慎重に設計する。

ステップ2: リトライ戦略を選択する

再試行の間隔とパターンを決める。

  • 固定間隔リトライ: 毎回同じ間隔で再試行(例: 1秒ごと)
  • 指数バックオフ: 間隔を指数的に増やす(例: 1秒→2秒→4秒→8秒)
  • ジッター付き指数バックオフ: バックオフにランダムな揺らぎを加える

ポイント: 分散システムではジッター付き指数バックオフが推奨。thundering herdを防ぐ。

ステップ3: リトライ回数の上限を設定する

無限にリトライしないよう、上限と最終的なフォールバックを設定する。

  • リトライ回数の上限(例: 最大3回)
  • 最大待機時間の上限(例: 合計30秒以内)
  • 上限に達した場合のフォールバック処理(エラー通知、キューへの退避など)

ポイント: リトライの上限を超えたら、サーキットブレーカーと連携して障害を確定させる。

ステップ4: リトライの状況をログ・メトリクスに記録する

リトライの発生状況を可視化し、システムの健全性を把握する。

  • リトライ回数、成功率、最終的な失敗率をメトリクスとして記録する
  • リトライが頻発している場合はアラートを発報する
  • リトライ成功率が低下傾向にあれば、根本原因の調査に着手する

ポイント: リトライは応急処置であり根本解決ではない。頻発するなら原因を追う。

具体例
#

例1:外部決済APIへのリクエストにリトライを適用する

状況: ECサイトの決済処理で外部APIを呼び出し。ネットワーク瞬断で月に数十回の一時的エラーが発生し、ユーザーに「もう一度お試しください」と表示。

リトライ戦略: ジッター付き指数バックオフ。最大3回。

  • 1回目: 1秒 +/- 0.5秒後
  • 2回目: 2秒 +/- 1秒後
  • 3回目: 4秒 +/- 2秒後

冪等性の確保: リクエストにユニークなidempotency-keyを付与し、二重課金を防止。

結果: 一時的エラーの95%が自動リトライで解消。ユーザーへのエラー表示が月数十回→月1〜2回に激減。

例2:メッセージキューのコンシューマーにリトライを組み込む

状況: SQSからメッセージを受信して処理するワーカー。外部API呼び出しの一時障害でメッセージが処理失敗→DLQ行き→手動再処理という運用が月50件発生。

改善: ワーカー内にリトライロジックを追加。

  • 1〜3回目: 指数バックオフでリトライ(合計15秒以内)
  • それでも失敗: SQSの可視性タイムアウトで自動再配信(5分後)
  • 5回失敗: DLQに退避+Slackアラート

結果: DLQ行きのメッセージが月50件→月3件に削減。手動再処理の運用工数がほぼゼロに。

例3:DB接続のリトライでデプロイ時の一時障害を吸収する

状況: RDSのフェイルオーバー時(約30秒間)にDB接続エラーが発生し、エラーレートが一時的に100%に。ヘルスチェック失敗でECSタスクが全て再起動し、復旧に5分以上かかる。

改善:

  • DB接続にリトライ(最大5回、指数バックオフ)を追加
  • ヘルスチェックにDB接続状態を含めない(アプリ自体は正常)
  • コネクションプールの再接続ロジックを強化

結果: RDSフェイルオーバー時のエラーレートが100%→0.5%に改善。ユーザーへの影響はp99の一時的な悪化(500ms→2秒)のみで、復旧時間は30秒に短縮。

やりがちな失敗パターン
#

  1. 冪等性を考慮せずにリトライする — リクエストが実は成功していたのにリトライして二重処理が発生する。冪等キーの付与状態確認APIで二重実行を防ぐ
  2. 固定間隔でリトライする — 障害時に全クライアントが同じタイミングでリトライし、サーバーをさらに圧迫する。指数バックオフ+ジッターを使う
  3. 永続的エラーにもリトライし続ける — バリデーションエラーなど何度やっても成功しないエラーへのリトライは無駄。エラーの種類を分類してリトライ対象を限定する
  4. リトライのメトリクスを取らない — リトライが成功しているから問題ないと思いがちだが、頻発は根本的な問題の兆候。リトライ率を監視し閾値でアラートする

まとめ
#

リトライパターンは分散システムにおける最も基本的な耐障害パターンの一つ。一時的な障害を自動的に吸収し、システムの信頼性を大幅に向上させる。ただし、冪等性の確保、適切なバックオフ戦略、リトライ上限の設定を怠ると逆効果になるため、設計時にこれらを必ず考慮しよう