Exponential Backoff Algorithm: Cara Kerja dan Implementasi

Exponential Backoff Algorithm adalah strategi penanganan kesalahan (error handling) yang digunakan dalam komunikasi jaringan dan komputasi terdistribusi, di mana klien secara berkala meningkatkan waktu tunggu (delay) di antara upaya percobaan ulang (retry) yang gagal. Algoritma ini sangat krusial untuk mencegah kelebihan beban pada server atau jaringan ketika terjadi lonjakan lalu lintas atau pemadaman layanan sementara.

Dalam praktiknya, jika sebuah permintaan ke server gagal karena timeout atau kesalahan server (seperti kode HTTP 503 atau 429), klien tidak langsung mencoba ulang secara instan. Alih-alih, klien menunggu selama durasi waktu dasar dikalikan dengan faktor eksponensial berdasarkan jumlah percobaan yang telah dilakukan. Penambahan elemen acak yang disebut jitter sering kali disematkan untuk mencegah fenomena thundering herd, di mana banyak klien mencoba terhubung kembali secara serentak pada detik yang sama.

Komponen Utama dan Rumus Matematika

Implementasi standar dari algoritma ini melibatkan beberapa variabel utama: waktu dasar (base interval), faktor penggali (multiplier), batas maksimum waktu tunggu (maximum backoff), dan jumlah percobaan maksimum (maximum retries).

Rumus dasar perhitungan waktu tunggu (delay) untuk percobaan ke-$n$ umumnya dinyatakan sebagai berikut:

delay = min(max_backoff, base * (multiplier ^ attempt))
Percobaan (Attempt) Perhitungan (Base = 1s, Multiplier = 2) Waktu Tunggu Teoretis Waktu Tunggu dengan Jitter (Acak)
1 1 * (2 ^ 1) 2 detik ~1.8 detik
2 1 * (2 ^ 2) 4 detik ~3.5 detik
3 1 * (2 ^ 3) 8 detik ~7.2 detik
4 1 * (2 ^ 4) 16 detik ~14.1 detik
5 1 * (2 ^ 5) 32 detik (Maksimum) ~28.4 detik

Contoh Implementasi Kode (Python)

Berikut adalah contoh kode nyata dalam bahasa Python untuk mengimplementasikan Exponential Backoff dengan penambahan Full Jitter guna mendistribusikan beban jaringan secara merata.

import time
import random
import requests

def api_request_with_backoff(url, max_retries=5):
    base_delay = 1
    max_delay = 32
    
    for attempt in range(max_retries):
        try:
            response = requests.get(url, timeout=5)
            if response.status_code == 200:
                return response.json()
            elif response.status_code in [429, 500, 502, 503, 504]:
                raise requests.exceptions.RequestException(f"Server error: {response.status_code}")
            else:
                # Kesalahan klien yang tidak dapat dipulihkan dengan retry
                response.raise_for_status()
        except requests.exceptions.RequestException as e:
            if attempt == max_retries - 1:
                raise Exception(f"Gagal setelah {max_retries} percobaan. Error terakhir: {e}")
            
            # Menghitung exponential backoff dengan batas maksimum
            temp = min(max_delay, base_delay * (2 ** attempt))
            
            # Menerapkan Full Jitter (waktu acak antara 0 dan temp)
            sleep_time = random.uniform(0, temp)
            
            print(f"Percobaan {attempt + 1} gagal. Menunggu selama {sleep_time:.2f} detik...")
            time.sleep(sleep_time)

Peran Penting Jitter dalam Sistem Skala Besar

Tanpa adanya jitter, algoritma backoff murni masih berisiko memicu sinkronisasi waktu antar klien. Ketika sebuah layanan mikro (microservices) mengalami gangguan sesaat, ribuan klien mungkin mendeteksi kegagalan pada detik yang sama. Jika seluruh klien tersebut menggunakan parameter dasar dan pengali yang identik, mereka akan meluncurkan percobaan ulang secara serentak pada detik ke-2, ke-4, ke-8, dan seterusnya.

Penerapan jitter memecah keselarasan ini dengan memasukkan unsur probabilitas acak. Beberapa varian jitter yang umum digunakan dalam industri meliputi:

  • Full Jitter: Mengambil nilai acak antara 0 dan nilai backoff terhitung. Ini memberikan distribusi beban yang paling merata.
  • Equal Jitter: Menyisakan setengah dari waktu tunggu secara deterministik dan mengacak setengah sisanya.
  • Decorrelated Jitter: Menghitung waktu tunggu berdasarkan waktu tunggu percobaan sebelumnya ditambah nilai acak tambahan.

Praktik Terbaik Penerapan di Lapangan

Dalam merancang sistem produksi yang handal, beberapa parameter teknis harus diperhatikan secara seksama:

  • Tentukan Batas Maksimum (Cap): Selalu tetapkan batas atas (maximum backoff) agar klien tidak harus menunggu hingga berjam-jam jika gangguan memanjang.
  • Batasi Jumlah Percobaan (Max Retries): Jangan melakukan percobaan ulang tanpa batas (infinite retry) yang dapat menghabiskan sumber daya memori dan koneksi soket klien.
  • Identifikasi Jenis Kesalahan: Jangan pernah melakukan retry pada kesalahan klien (misalnya HTTP 400 Bad Request atau 401 Unauthorized), karena permintaan tersebut dijamin akan terus gagal tanpa perubahan parameter. Retry hanya diperuntukkan bagi kesalahan jaringan sementara atau kesalahan sisi server (5xx).