指数バックオフ

リトライ間隔を指数関数的に増加させ、障害時のシステム負荷を軽減するリトライ戦略

耐障害性設計

指数バックオフとは

指数バックオフ (Exponential Backoff) は、リトライ間隔を指数関数的に増加させ、障害時のシステム負荷を軽減するリトライ戦略である。AWS SDK はデフォルトで指数バックオフを実装している。

リトライ間隔

リトライ 1: 1 秒後
リトライ 2: 2 秒後
リトライ 3: 4 秒後
リトライ 4: 8 秒後
リトライ 5: 16 秒後 (最大リトライ回数に達したら失敗)

計算式: delay = min(base * 2^attempt, maxDelay)

ジッター (Jitter)

❌ ジッターなし:
  100 クライアントが同時にリトライ → 再び過負荷

✅ ジッターあり:
  各クライアントがランダムな遅延を追加 → 負荷が分散

Full Jitter: delay = random(0, base * 2^attempt)
Equal Jitter: delay = base * 2^attempt / 2 + random(0, base * 2^attempt / 2)

TypeScript での実装

async function withRetry<T>(
  fn: () => Promise<T>,
  maxAttempts = 3,
  baseDelay = 1000,
): Promise<T> {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    try {
      return await fn();
    } catch (e) {
      if (attempt === maxAttempts - 1) throw e;
      const delay = Math.min(baseDelay * 2 ** attempt, 30000);
      const jitter = Math.random() * delay; // Full Jitter
      await new Promise(r => setTimeout(r, jitter));
    }
  }
  throw new Error('Unreachable');
}

AWS SDK のリトライ

import { DynamoDBClient } from '@aws-sdk/client-dynamodb';

const client = new DynamoDBClient({
  maxAttempts: 5, // デフォルト: 3
  // SDK が自動的に指数バックオフ + ジッターでリトライ
});

リトライすべきエラー

ステータス リトライ 理由
429 レート制限 (一時的)
500 サーバーエラー (一時的)
503 サービス利用不可 (一時的)
400 クライアントエラー (修正が必要)
404 リソースが存在しない

Step Functions のリトライ

ProcessPayment:
  Type: Task
  Resource: !GetAtt PaymentFunction.Arn
  Retry:
    - ErrorEquals: [ServiceException, TooManyRequestsException]
      IntervalSeconds: 2
      MaxAttempts: 3
      BackoffRate: 2  # 2秒 → 4秒 → 8秒
  Catch:
    - ErrorEquals: [States.ALL]
      Next: HandleFailure

指数バックオフの注意点

注意点 対策
最大遅延の上限 30 秒程度にキャップ
最大リトライ回数 3〜5 回で打ち切り
冪等性の確保 リトライで副作用が重複しないように
タイムアウトとの整合 Lambda のタイムアウト内に収める

理論と実装の両面から学ぶなら関連書籍が参考になる。

関連用語