Belajar RoadRunner - Cluster, Multisite & High Availability
Episode 22 of 26

Belajar RoadRunner - Cluster, Multisite & High Availability

Meningkatkan RoadRunner ke skala cluster: memperbanyak replica, menghilangkan sticky session dengan store Redis, membagikan queue antar node, menjaga state konsisten, dan menyusun strategi zero-downtime deployment.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 21 kita men-deploy satu aplikasi ke Kubernetes, pada episode kali ini kita menaikkan skala: cluster, multisite & high availability. Satu replica tidak pernah cukup untuk production yang serius — dan begitu ada banyak node, muncul masalah yang tidak ada di single node: session harus dibagikan, queue harus konsisten, dan deployment tidak boleh memutus user.

Mengapa episode ini penting? Karena hampir semua aturan yang kita pelajari sejak episode 10 (state di store eksternal) baru terasa manfaatnya di skala ini. Cluster adalah ujian sejati arsitektur stateless.

Model Cluster RoadRunner

RoadRunner adalah aplikasi stateless secara alami: server Go hanya mengelola worker dan plugin; data hidup di store eksternal. Karena itu cluster adalah kumpulan replica identik yang masing-masing berjalan normal:

100%

Tidak ada sinkronisasi antar replica karena tidak ada state lokal yang perlu disinkronkan — selama semua state "lintas-request" hidup di Redis/DB.

Menghilangkan Sticky Session

Di banyak setup PHP-FPM, session tersimpan di file lokal → butuh sticky session (load balancer memaksa user ke node yang sama). Di RoadRunner, ini seharusnya tidak perlu. Pola yang benar (dari episode 10 dan 14):

Session di store bersama
$sessionId = $request->getCookieParams()['session'] ?? bin2hex(random_bytes(16));
$key = 'session:' . $sessionId;
$data = $cache->get($key) ?? [];
 
// ... mutasi data ...
$cache->set($key, $data, 1800);

Karena session ada di Redis bersama, replica mana pun bisa melayani request user mana pun. Load balancer bisa memakai round-robin sederhana tanpa affinity — dan ketika satu replica mati, request tetap diproses node lain tanpa kehilangan session.

Tip

Jika kalian menemukan config load balancer yang memaksa sticky session, itu sinyal aplikasi masih menyimpan state di worker (pelanggaran episode 14). Pindahkan state ke store eksternal, lalu hapus sticky session — cluster menjadi lebih tangguh dan lebih mudah di-scale.

Queue Terdistribusi

Queue (episode 11) juga harus dibagikan antar node. Gunakan driver yang bersifat terpusat — Redis, AMQP, atau SQS — bukan Boltdb lokal:

Pipeline queue terpusat
jobs:
  consume:
    - queue: "emails"
      pipeline: "redis-emails"
  pipelines:
    redis-emails:
      driver: redis
      config:
        addr: ${REDIS_ADDR}
        queue: emails

Saat satu node mem-push job, node lain yang idle akan menariknya — pekerjaan didistribusikan otomatis. Untuk job dengan prioritas/latensi tinggi, pertimbangkan AMQP/RabbitMQ dengan exchange yang lebih kaya; untuk volume raksasa, SQS.

Konsistensi State di Cluster

Aturan praktis state di cluster:

Jenis stateTempatKonsisten lintas node?
SessionRedis/KVYa
CacheRedis/KVYa
QueueRedis/AMQP/SQSYa
Data bisnisDatabaseYa
State di memory workerTidak — dilarang
Store memory/file KVLocalTidak — hindari untuk data penting

Satu-satunya cara data bisa berbeda antar node adalah bila kalian memakai store KV memory/file (local) atau menyimpan state di worker. Audit ini sekali dan cluster kalian aman.

Zero-Downtime Deployment

Kombinasi teknik dari episode 21 untuk update tanpa downtime:

  1. Rolling update (Kubernetes default): pod baru lahir, readiness pass, pod lama menerima SIGTERM — request tidak terputus.
  2. Canary release: naikkan replica versi baru sedikit, amati metric (episode 12), baru naikkan penuh.
  3. DB migration kompatibel: deploy yang menambahkan kolom/tabel tidak boleh memutus versi lama (expand-contract).
  4. Queue drain: sebelum mematikan versi lama, pastikan worker jobs selesai; naikkan terminationGracePeriodSeconds saat antrian penuh.

Contoh strategi rolling update:

KubernetesRolling update strategy
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1

maxUnavailable: 0 + maxSurge: 1 berarti satu pod baru dibangun sebelum satu pod lama dihapus — kapasitas penuh selalu tersedia.

Warning

Zero-downtime hanya berlaku bila semua state bersifat eksternal. Bila satu pod menyimpan state lokal (misal file session atau memory KV), request yang berpindah node akan kehilangan state. Cluster dan zero-downtime adalah dua alasan mengapa aturan episode 14 tidak bisa ditawar.

Multisite / Multi-Region

Untuk multisite (domain berbeda, codebase sama) atau multi-region:

  • Pisahkan store per site/region: Redis per region dengan replication, DB per site atau sharding.
  • Queue tetap terpusat bila job harus diproses satu region (misal sesuai data residency).
  • Load balancer per region, dengan failover lintas region untuk high availability.

Pola ini lebih kompleks, tetapi fondasinya sama: server tetap stateless; pemisahan terjadi di lapisan data.

Penutup

Pada episode 22 ini, kalian telah membawa RoadRunner ke skala cluster.

Inti yang harus dibawa pulang:

  • Cluster = banyak replica identik + store eksternal bersama.
  • Session di Redis menghilangkan kebutuhan sticky session.
  • Queue memakai driver terpusat (Redis/AMQP/SQS), bukan lokal.
  • Audit: tidak ada state worker yang boleh bocor antar node.
  • Zero-downtime: rolling update + canary + migrasi kompatibel.

Di episode 23 selanjutnya, kita masuk ke kustomisasi: custom plugins & Velox — membangun binary RoadRunner sendiri dengan plugin Go tambahan, menulis plugin kustom, dan mengintegrasikannya ke aplikasi PHP. Sampai jumpa di episode 23!