Pukul 20.00 malam flash sale, checkout TokoKita berhenti merespons selama 40 menit karena satu worker ETL dan satu database berbagi nasib di server yang sama. Setiap menit gangguan berarti pembeli beralih ke toko pesaing, dan total kerugian jauh melampaui biaya server cadangan yang tidak pernah dipasang. High availability (HA) adalah disiplin merancang sistem agar kegagalan satu komponen tidak menghentikan layanan. Chapter ini menghitung matematikanya secara nyata, mengaudit arsitektur TokoKita dari single point of failure, lalu menerjemahkan janji SLA penyedia cloud menjadi anggaran downtime.

Redundansi dan Matematika Ketersediaan #

Konsep dasarnya sudah kita kenal dari Chapter Fault Tolerance dan Replication: sistem tetap hidup selama minimal satu salinan masih bekerja. Pertanyaannya sekarang kuantitatif — berapa persen ketersediaan yang dibeli oleh N worker? Simulasi berikut menghitungnya dengan asumsi eksplisit: tiap worker tersedia 99% setahun, tiap Availability Zone (AZ) tersedia 99,9%, dan layanan dianggap hidup bila minimal satu worker berjalan.

python
"""Matematika ketersediaan: redundansi worker, single-AZ vs multi-AZ,
anggaran downtime SLA, dan SLA komposit. Layanan dianggap hidup bila
minimal satu worker tersedia."""
P_NODE = 0.99     # ketersediaan per worker setahun (ilustratif)
P_AZ = 0.999      # ketersediaan per Availability Zone (gangguan zona)
JUMLAH_AZ = 3
JAM_TAHUN = 8760


def ketersediaan(n_worker, az_terpakai):
    """n worker disebar rata; layanan hidup bila >=1 worker hidup di >=1 AZ."""
    az = min(n_worker, az_terpakai)
    k, sisa = divmod(n_worker, az)
    p_mati = 1.0
    for i in range(az):
        ki = k + (1 if i < sisa else 0)
        segmen = P_AZ * (1 - (1 - P_NODE) ** ki)   # segmen AZ tetap hidup
        p_mati *= 1 - segmen                        # semua AZ mati bersamaan
    return 1 - p_mati


def fmt_avail(a):
    s = f"{a*100:.4f}%"
    return ">99.9999%" if s.startswith("100") else s


def fmt_dt(jam):
    if jam >= 1:
        return f"{jam:.2f} jam"
    return f"{jam*60:.1f} menit" if jam * 60 >= 1 else f"{jam*3600:.2f} detik"


print(f"Model: p_node={P_NODE}, p_az={P_AZ}, hidup bila >=1 worker hidup\n")
print("| Worker | Single-AZ | Multi-AZ (3 AZ) | Downtime dihemat/tahun |")
print("|---|---|---|---|")
for n in (1, 2, 3, 5, 10):
    satu, multi = ketersediaan(n, 1), ketersediaan(n, JUMLAH_AZ)
    ds, dm = (1 - satu) * JAM_TAHUN, (1 - multi) * JAM_TAHUN
    print(f"| {n} | {fmt_avail(satu)} ({fmt_dt(ds)}) | "
          f"{fmt_avail(multi)} ({fmt_dt(dm)}) | {ds - dm:.2f} jam |")

print("\nAnggaran downtime per tingkat SLA:")
print("| SLA | Per tahun (8760 jam) | Per bulan (730 jam) | Per minggu (168 jam) |")
print("|---|---|---|---|")
for sla in (0.99, 0.999, 0.9995, 0.9999):
    print(f"| {sla*100:g}% | {fmt_dt((1-sla)*8760)} | "
          f"{fmt_dt((1-sla)*730)} | {fmt_dt((1-sla)*168)} |")

print("\nSLA komposit rangkaian (semua komponen wajib hidup):")
hasil = 1.0
for nama, p in (("Load balancer", 0.9999), ("Tier aplikasi", 0.999),
                ("Database", 0.9995)):
    hasil *= p
    print(f"  {nama:<14} {p*100:g}% -> komposit {hasil*100:.4f}%")
print(f"SLA komposit akhir {hasil*100:.4f}% = downtime "
      f"{(1-hasil)*JAM_TAHUN:.2f} jam/tahun")

Output yang Dihasilkan:

text
Model: p_node=0.99, p_az=0.999, hidup bila >=1 worker hidup

| Worker | Single-AZ | Multi-AZ (3 AZ) | Downtime dihemat/tahun |
|---|---|---|---|
| 1 | 98.9010% (96.27 jam) | 98.9010% (96.27 jam) | 0.00 jam |
| 2 | 99.8900% (9.64 jam) | 99.9879% (1.06 jam) | 8.58 jam |
| 3 | 99.8999% (8.77 jam) | 99.9999% (41.86 detik) | 8.76 jam |
| 5 | 99.9000% (8.76 jam) | >99.9999% (0.42 detik) | 8.76 jam |
| 10 | 99.9000% (8.76 jam) | >99.9999% (0.03 detik) | 8.76 jam |

Anggaran downtime per tingkat SLA:
| SLA | Per tahun (8760 jam) | Per bulan (730 jam) | Per minggu (168 jam) |
|---|---|---|---|
| 99% | 87.60 jam | 7.30 jam | 1.68 jam |
| 99.9% | 8.76 jam | 43.8 menit | 10.1 menit |
| 99.95% | 4.38 jam | 21.9 menit | 5.0 menit |
| 99.99% | 52.6 menit | 4.4 menit | 1.0 menit |

SLA komposit rangkaian (semua komponen wajib hidup):
  Load balancer  99.99% -> komposit 99.9900%
  Tier aplikasi  99.9% -> komposit 99.8900%
  Database       99.95% -> komposit 99.8401%
SLA komposit akhir 99.8401% = downtime 14.01 jam/tahun

Mari kita telaah baris-baris kode di atas:

  1. Baris 10-19 (ketersediaan): worker disebar rata ke az segmen. Ketersediaan tiap segmen adalah p_az × (1-(1-p_node)^k) — AZ harus hidup dan minimal satu worker di dalamnya hidup. Layanan hanya berhenti bila semua segmen gagal bersamaan, sehingga peluangnya dikalikan.
  2. Baris 27-32 (tabel redundansi): baris pertama membuktikan satu worker hanya bisa berada di satu AZ, sehingga single-AZ dan multi-AZ identik. Redundansi baru berarti mulai dua worker.
  3. Baris 45-49 (SLA komposit): SLA rangkaian adalah hasil kali SLA komponen karena semuanya wajib hidup. Setiap komponen baru hanya bisa menurunkan komposit.

Tiga pembacaan penting muncul dari tabel. Pertama, menambah worker di satu AZ berhenti berguna di angka 99,9% — itulah plafon ketersediaan AZ itu sendiri; gangguan zona menelan 8,76 jam per tahun apa pun yang kita lakukan. Kedua, menyebarkan worker ke beberapa AZ membeli lompatan besar: tiga worker multi-AZ mencapai 99,9999% atau sekitar 42 detik downtime per tahun. Ketiga, SLA komposit 99,8401% lebih rendah dari komponen terlemah di rantainya — menambah tier aplikasi justru memperburuk angka, bukan memperbaiki.

Audit SPOF Arsitektur TokoKita #

Single point of failure (SPOF) adalah komponen yang kegagalannya sendirian menghentikan keseluruhan layanan. Audit dilakukan dengan menelusuri setiap komponen arsitektur dan bertanya: apa yang terjadi bila komponen ini berhenti?

KomponenStatusPerbaikan
Scheduler orkestrasi tunggalSPOFmode HA dua node dengan leader standby
Worker ETL tunggalSPOFfleet autoscaling dengan minimum dua worker di dua AZ
Database single-instanceSPOFdeployment multi-AZ dengan standby sinkron
NAT gateway satu-satunyaSPOF untuk egresssatu NAT per AZ, route per subnet
Load balancer terkelolabukan SPOFsudah multi-AZ by default
Object storage regionalbukan SPOFtahan kegagalan AZ secara desain

Perubahan penting di sisi “sesudah” adalah munculnya antrean pesan di antara scheduler dan worker — menyerap lonjakan beban sekaligus memutus ketergantungan langsung, pola yang dipadukan dengan autoscaling dari Chapter Autoscaling. Untuk lapisan database, opsi multi-AZ pada managed service yang dibahas di Chapter Managed Data Services mengurus replikasi dan failover otomatis; mekanika replikasinya sendiri telah dibedah di Chapter Replikasi Database.

Menerjemahkan SLA ke Anggaran Downtime #

Angka SLA mudah terdengar mengesankan sampai diterjemahkan ke waktu. SLA 99,9% — angka yang sering diiklankan — berarti anggaran downtime 8,76 jam per tahun, atau 43,8 menit per bulan. Pertanyaan bagi bisnis bukan “berapa persen”, melainkan “berapa menit dan siapa yang menanggung”. Daftar region dan AZ di tiap penyedia dapat dibandingkan di AWS Well-Architected Reliability Pillar dan Regions and zones Google Cloud .

Perlu dicatat pula bahwa SLA penyedia hanya mengukur ketersediaan layanan penyedia itu sendiri, bukan aplikasi kita. Database bisa 99,99% tersedia sementara pipeline yang mengisinya rusak karena bug — ketersediaan data dan ketersediaan layanan adalah dua ukuran berbeda, dan keduanya harus dipantau terpisah.

Arsitektur yang tahan kegagalan komponen dan zona kini lengkap: jaringan tersegmentasi, layanan terkelola, fleet elastis, backup lintas region, dan redundansi multi-AZ. Satu pertanyaan strategis tersisa untuk menutup section ini: penyedia cloud mana yang paling cocok untuk keseluruhan platform data TokoKita? Chapter Pemilihan Cloud Platform menyusun kerangka keputusannya.