Phase 5레슨 22

Retry & Timeout

Exponential Backoff, Jitter, Timeout Budget, Hedging — 실패한 요청을 어떻게 재시도할 것인가

💡ELI5·

전화 재시도와 Retry Storm

서버 장애 (1초):
  1000개 요청 → 실패 → 1초 후 1000개 재시도 → 또 실패 → 2초 후 1000개...
  → 서버가 복구되려는 순간 또 재시도 폭주 → 영영 복구 불가

해결 (Backoff + Jitter):
  요청1: 1.2초 후 재시도
  요청2: 1.8초 후 재시도
  요청3: 2.1초 후 재시도  ← 분산됨
  → 서버가 틈틈이 회복 가능
💡 비유친구에게 전화가 안 걸려서 100명이 동시에 1초 간격으로 재다이얼하면, 기지국이 폭주해서 아무도 못 건다. 각자 랜덤한 시간에 재다이얼하면 기지국이 여유를 갖고 처리할 수 있다.
🔬Deep Dive·

Exponential Backoff + Jitter

// 잘못된 재시도: 고정 간격 (동기화 폭주)
async function retryBad(fn) {
  for (let i = 0; i < 3; i++) {
    try { return await fn(); }
    catch { await sleep(1000); } // 모든 클라이언트가 1초 후 동시 재시도
  }
}

// 올바른 재시도: Exponential Backoff + Full Jitter
async function retryGood(fn) {
  const base = 1000; // 1초
  const cap = 30000; // 최대 30초
  for (let i = 0; i < 5; i++) {
    try { return await fn(); }
    catch (e) {
      if (i === 4) throw e;
      const exp = Math.min(cap, base * 2 ** i);
      const jitter = Math.random() * exp; // 0 ~ exp 사이 무작위
      await sleep(jitter);
    }
  }
}
Jitter 방식공식특징
Full Jitterrandom(0, base * 2^n)가장 분산이 큼, AWS 권장
Equal Jitterbase/2 + random(0, base/2^n / 2)최소 대기 시간 보장
Decorrelated Jitterrandom(base, prev_sleep * 3)이전 대기 시간 기반
🔬Deep Dive·

Timeout Budget

사용자 요청 (총 5초 예산)
  ├── API Gateway: 4.5초
  │   ├── 인증: 0.5초
  │   └── 주문 서비스: 3.5초
  │       ├── DB 쓰기: 1.5초
  │       └── 결제 서비스 호출: 2초
  └── 응답 직렬화: 0.5초

하위 타임아웃 합 ≤ 상위 타임아웃
→ 결제가 2초 초과하면 주문 서비스가 끊어냄 (사용자 대기 방지)
하위 서비스의 타임아웃이 상위보다 길면, 상위가 먼저 타임아웃되어 사용자는 에러를 보지만 하위는 계속 처리 → 자원 낭비. 반드시 하위 ≤ 상위.
⚖️Trade-off·

재시도의 Trade-off

이점위험
일시적 장애 자동 복구Retry Storm으로 장애 악화
사용자 경험 개선 (재시도 후 성공)비멱등 연산 시 중복 부작용
꼬리 지연 감소 (Hedging)서버 부하 증가 (Hedging 2배)
재시도 중첩으로 지연 누적

❓ 체크포인트 질문

  1. 1.단순 재시도가 위험한 이유는?
  2. 2.Exponential Backoff에 Jitter가 필요한 이유는?
  3. 3.Timeout Budget이 무엇인가?
  4. 4.Hedging Request가 무엇이고 언제 유용한가?
  5. 5.재시도하면 안 되는 상황은?