Питання 20 · Розділ 17

Що таке exponential backoff

Structured Java interview answer with junior, middle, and senior-level explanation.

Мовні версії: English Russian Ukrainian

🟢 Junior Level

Exponential backoff — стратегія retry, де час очікування подвоюється після кожної невдалої спроби.

Спроба 1: помилка → чекати 1 сек
Спроба 2: помилка → чекати 2 сек
Спроба 3: помилка → чекати 4 сек
Спроба 4: помилка → чекати 8 сек
Спроба 5: успіх! ✅

Навіщо: Якщо сервіс перевантажений, дати йому більше часу на відновлення.


🟡 Middle Level

Реалізація

// ⚠️ ПОГАНИЙ приклад для production: Thread.sleep блокує потік,
// немає jitter, немає max cap. Використовуйте Resilience4j або Spring Retry.
long baseDelay = 1000; // 1 секунда
double multiplier = 2.0;

for (int attempt = 0; attempt < maxAttempts; attempt++) {
    try {
        return callService();
    } catch (Exception e) {
        long delay = (long) (baseDelay * Math.pow(multiplier, attempt));
        Thread.sleep(delay);
    }
}

З jitter

// Jitter додає випадковість для запобігання thundering herd
// Це "equal jitter" варіант. AWS рекомендує "full jitter":
// sleep = random(0, min(cap, base * 2^attempt))
long delay = (long) (baseDelay * Math.pow(multiplier, attempt));
long jitter = random.nextInt((int)(delay * 0.1));
delay += jitter;

Типові помилки

  1. Без jitter:
    Усі клієнти retry одночасно → thundering herd → сервіс знову падає
    

Коли НЕ використовувати exponential backoff

  • Ідемпотентні read-операції — простий retry ok
  • Критичні за часом операції (real-time) — backoff додає непередбачуваність
  • Клієнтські запити від користувача — користувач не чекатиме 30 секунд backoff

🔴 Senior Level

Full jitter formula

// AWS рекомендує: full jitter
long delay = min(cap, base * pow(multiplier, attempt)) + random(0, base)

Production Experience

Resilience4j:

RetryConfig config = RetryConfig.custom()
    .maxAttempts(5)
    .intervalFunction(IntervalFunction.ofExponentialBackoff(1000, 2.0))
    .build();

Best Practices

✅ Exponential backoff + jitter
✅ Cap на максимальну затримку
✅ Ліміт спроб
✅ Тільки для retryable помилок

❌ Без cap (можна чекати хвилини)
❌ Без jitter
❌ Для всіх типів помилок

🎯 Шпаргалка для співбесіди

Обов’язково знати:

  • Exponential backoff — delay подвоюється: 1s → 2s → 4s → 8s
  • Jitter додає випадковість: AWS рекомендує full jitter = random(0, min(cap, base * 2^attempt))
  • Cap (максимальна затримка) обов’язковий — без cap можна чекати хвилини
  • Тільки для retryable помилок — не для 4xx, не для business exceptions
  • НЕ використовувати для ідемпотентних read (простий retry ok), real-time операцій, клієнтських запитів
  • Resilience4j: IntervalFunction.ofExponentialBackoff(base, multiplier)
  • Thread.sleep у production — погано, використовуйте Resilience4j або Spring Retry

Часті уточнюючі питання:

  • Full jitter vs equal jitter? Full jitter = random(0, base2^attempt), equal jitter = delay + random(0, delay0.1). Full jitter краще запобігає thundering herd.
  • Який cap обрати? Залежить від SLA — зазвичай 30-60 секунд максимум.
  • Чому Thread.sleep поганий? Блокує потік, немає jitter, немає max cap — використовуйте Resilience4j.
  • Коли НЕ використовувати backoff? Read-операції (простий retry ok), real-time, клієнтські запити від користувача.

Червоні прапорці (НЕ говорити):

  • “Backoff без cap — надійніший” — ні, можна чекати нескінченно
  • “Jitter не потрібен для малого трафіку” — все одно потрібен, клієнти можуть синхронізуватися
  • “Backoff для 404 помилок” — ні, сервіс не полагодиться сам
  • “Thread.sleep — production-ready” — ні, блокує потік, немає jitter

Пов’язані теми:

  • [[19. Що таке патерн Retry і як його правильно використовувати]]
  • [[17. Як забезпечити відмовостійкість мікросервісів]]
  • [[15. Як організувати комунікацію між мікросервісами]]
  • [[5. Що таке патерн Circuit Breaker]]
  • [[21. Як моніторити розподілену систему мікросервісів]]