Apa itu Clustering?
Clustering itu konsep di mana beberapa server (node) bekerja sama sebagai satu unit untuk mencapai tujuan tertentu — bisa availability, performance, atau keduanya.
Dari luar, user ga tahu (dan ga perlu tahu) bahwa di baliknya ada banyak server. Mereka cuma lihat satu sistem yang jalan.
Bayangin restoran. Kalau cuma satu koki, kapasitasnya terbatas. Antrian panjang, kalau si koki sakit restoran tutup. Tapi kalau ada 5 koki yang kerja bareng di satu dapur, mereka bisa handle lebih banyak order, dan kalau satu koki izin, yang lain bisa cover.
Lima koki itu = cluster. Dapur itu = sistem. Pelanggan cuma tahu makanan keluar, ga peduli koki mana yang masak.
Kenapa Butuh Cluster?
1. Satu server punya batas
Secanggih apapun server kamu, ada batasnya.
- CPU mentok? Ga bisa handle lebih banyak request
- RAM penuh? Mulai swap ke disk, lambat drastis
- Disk penuh? Game over
Vertical scaling (upgrade server yang ada: tambah RAM, ganti CPU) ada ceiling-nya. Dan makin ke atas, makin mahal per unit peningkatan.
2. Satu server itu single point of failure
Sudah dibahas di catatan High Availability. Satu server mati = seluruh sistem mati.
Cluster mengeliminasi ini. Node mati? Cluster tetap jalan.
3. Horizontal scaling lebih sustainable
Daripada beli satu server super mahal, lebih baik beli banyak server biasa dan kluster-kan.
graph LR
subgraph Vertical Scaling
A["1 Server Rp500jt<br/>(32 CPU, 256GB RAM)"]
end
subgraph Horizontal Scaling
B["Server 1<br/>Rp50jt"]
C["Server 2<br/>Rp50jt"]
D["Server 3<br/>Rp50jt"]
E["..."]
end
Horizontal scaling secara teori ga ada batasnya — tinggal tambah node. Dan total cost biasanya lebih murah.
Tipe-Tipe Cluster
1. High Availability (HA) Cluster
Tujuannya: sistem tetap hidup meskipun ada node yang mati.
Fokusnya bukan speed, tapi uptime. Kalau node primary mati, node lain ambil alih.
Contoh: database cluster di mana kalau primary mati, replica otomatis di-promote.
graph LR
Client --> VIP["Virtual IP"]
VIP --> N1["Node 1 (Primary)"]
VIP -.->|failover| N2["Node 2 (Standby)"]
Node punya Virtual IP (VIP) yang "mengambang" — mengarah ke node primary. Kalau primary mati, VIP pindah ke standby. Client ga perlu tahu node mana yang jadi primary karena IP-nya tetap sama.
2. Load Balancing Cluster
Tujuannya: distribusi beban ke banyak node supaya ga ada yang overload.
Semua node aktif dan melayani request secara bersamaan.
graph LR
Client --> LB[Load Balancer]
LB --> N1[Node 1]
LB --> N2[Node 2]
LB --> N3[Node 3]
LB --> N4[Node 4]
Bedanya sama HA cluster: di sini semua node kerja bareng, bukan satu aktif dan sisanya standby. Kalau satu mati, yang lain handle extra traffic.
3. Storage Cluster
Tujuannya: simpan data secara terdistribusi di banyak node supaya data aman dan bisa diakses cepat.
Data dipecah (sharding) dan/atau di-copy (replication) ke beberapa node.
graph TB
subgraph Storage Cluster
N1["Node 1<br/>Data A, B"]
N2["Node 2<br/>Data B, C"]
N3["Node 3<br/>Data C, A"]
end
Client --> N1
Client --> N2
Client --> N3
Setiap data ada di minimal 2 node. Node 1 mati? Data A masih ada di Node 3, Data B masih ada di Node 2.
Contoh: GlusterFS, Ceph, HDFS, Cassandra.
Kombinasi
Banyak sistem modern gabungin ketiga tipe ini. Kubernetes misalnya, itu cluster yang menggabungkan HA (control plane redundant), load balancing (service distribution), dan storage (persistent volumes).
Arsitektur Cluster
Shared-Nothing Architecture
Setiap node punya resource sendiri (CPU, RAM, disk) dan ga berbagi resource dengan node lain.
graph TB
subgraph Node 1
C1[CPU] --- M1[RAM] --- D1[Disk]
end
subgraph Node 2
C2[CPU] --- M2[RAM] --- D2[Disk]
end
subgraph Node 3
C3[CPU] --- M3[RAM] --- D3[Disk]
end
Node_1_label[" "] ~~~ Node_2_label[" "] ~~~ Node_3_label[" "]
Komunikasi antar node cuma lewat network messages.
- Pro: scalability tinggi, ga ada contention untuk shared resources
- Con: data synchronization lebih complex, harus handle network failures
- Contoh: Cassandra, MongoDB sharded cluster, Kafka
Shared-Disk Architecture
Semua node berbagi disk/storage yang sama, tapi punya CPU dan RAM sendiri.
graph TB
N1[Node 1<br/>CPU + RAM]
N2[Node 2<br/>CPU + RAM]
N3[Node 3<br/>CPU + RAM]
N1 --> SAN[(Shared Storage<br/>SAN/NAS)]
N2 --> SAN
N3 --> SAN
- Pro: semua node lihat data yang sama, ga perlu replikasi
- Con: shared storage jadi bottleneck dan SPOF. Butuh storage yang mahal dan redundant
- Contoh: Oracle RAC, IBM DB2 pureScale
Leader Election
Di setiap cluster, ada pertanyaan fundamental: siapa yang jadi "bos"?
Banyak arsitektur cluster butuh satu node yang jadi leader (atau primary/master) yang koordinasi kerja node lain.
Kenapa perlu leader?
Tanpa leader:
- Siapa yang terima write ke database?
- Siapa yang assign tugas?
- Siapa yang bikin keputusan kalau ada konflik?
Semua node terima write secara independen? Data bisa conflict. Chaos.
Dengan leader:
- Write masuk ke leader → leader distribusi ke followers
- Leader assign tugas → coordination jelas
- Ada konflik? Leader yang putuskan
Gimana cara milih leader?
Bully Algorithm
Paling simpel. Node dengan ID tertinggi yang jadi leader.
sequenceDiagram
participant N1 as Node 1 (ID: 1)
participant N2 as Node 2 (ID: 2)
participant N3 as Node 3 (ID: 3)
Note over N1,N3: Node 3 (leader) mati
N1->>N2: Election! Saya mau jadi leader
N2->>N1: Ga bisa, ID saya lebih tinggi
N2->>N3: Election! (ga ada response, mati)
Note over N2: Node 2 jadi leader baru
- Node detect leader mati → mulai election
- Kirim pesan ke semua node dengan ID lebih tinggi
- Kalau ada yang lebih tinggi, dia yang ambil alih
- Kalau ga ada yang response, kamu jadi leader
Simpel tapi ada masalah: ga fault-tolerant banget. Node dengan ID tertinggi yang lagi slow tapi belum mati bisa bikin election berulang-ulang.
Raft Consensus
Ini yang lebih modern dan banyak dipake di production. Raft itu consensus algorithm yang didesain supaya mudah dipahami.
Sebelum Raft, ada Paxos — consensus algorithm yang ditulis oleh Leslie Lamport di tahun 1989 (meskipun baru dipublikasikan tahun 1998). Fungsinya sama: bikin banyak node setuju pada satu nilai. Tapi Paxos terkenal sangat susah dipahami — bahkan paper aslinya ditulis kayak cerita fiksi tentang pulau Yunani kuno. Raft dibuat tahun 2014 literally karena Paxos terlalu susah. Judul paper-nya aja: "In Search of an Understandable Consensus Algorithm."
Di Raft, setiap node ada di salah satu dari tiga state:
stateDiagram-v2
[*] --> Follower
Follower --> Candidate: Timeout, ga denger dari leader
Candidate --> Leader: Dapat majority vote
Candidate --> Follower: Kalah election
Leader --> Follower: Discover node lain punya term lebih tinggi
Follower: listen ke leader. Kalau lama ga denger dari leader, dia curiga leader mati.
Candidate: node yang mau jadi leader. Dia kirim "vote for me" ke semua node.
Leader: node yang menang election. Dia kirim heartbeat berkala ke semua follower supaya mereka tahu dia masih hidup.
Election process di Raft:
- Follower ga denger heartbeat dari leader selama election timeout (random, misal 150-300ms)
- Follower berubah jadi Candidate
- Candidate naikin term (semacam epoch/generation number) dan vote untuk dirinya sendiri
- Candidate kirim RequestVote ke semua node lain
- Node lain vote kalau:
- Belum vote di term ini
- Candidate punya log yang up-to-date
- Dapat majority vote (lebih dari setengah) → jadi Leader
- Leader mulai kirim heartbeat ke semua follower
Kenapa election timeout-nya random?
Supaya ga semua follower jadi candidate barengan. Kalau timeout-nya fixed:
Node A: timeout → jadi candidate
Node B: timeout → jadi candidate (bersamaan!)
Node C: timeout → jadi candidate (bersamaan!)
Semua saling vote untuk diri sendiri. Ga ada yang dapet majority. Split vote — election gagal.
Dengan random timeout (misal 150-300ms):
Node A: timeout 167ms → jadi candidate duluan → kirim vote request
Node B: timeout 243ms → terima vote request dari A → vote untuk A
Node C: timeout 289ms → terima vote request dari A → vote untuk A
Node A kemungkinan besar menang karena duluan. Simple but effective.
Consensus: Gimana Cluster Setuju?
Consensus itu salah satu problem paling fundamental di distributed systems. Pertanyaannya: gimana caranya semua node setuju pada satu nilai yang sama, meskipun ada node yang gagal atau network yang ga reliable?
Kenapa ini susah?
Di dunia ideal:
- Node A bilang "nilai X = 5"
- Semua node terima pesan itu
- Semua setuju X = 5
Di dunia nyata:
- Pesan bisa delay, hilang, atau duplikat
- Node bisa crash di tengah-tengah proses
- Network bisa partisi (node A bisa bicara ke B tapi ga ke C)
- Node bisa restart dan lupa apa yang udah di-agree
Log Replication di Raft
Setelah leader terpilih, dia bertanggung jawab replicate semua perubahan ke follower.
sequenceDiagram
participant C as Client
participant L as Leader
participant F1 as Follower 1
participant F2 as Follower 2
C->>L: Write X = 5
L->>L: Tulis ke log (uncommitted)
L->>F1: AppendEntries (X = 5)
L->>F2: AppendEntries (X = 5)
F1-->>L: OK, sudah ditulis
F2-->>L: OK, sudah ditulis
Note over L: Majority confirm → commit!
L->>F1: Commit X = 5
L->>F2: Commit X = 5
L-->>C: Write sukses
Step by step:
- Client kirim write ke Leader
- Leader tulis ke log-nya sendiri (belum committed)
- Leader kirim entry ke semua Follower
- Follower tulis ke log mereka
- Kalau majority (termasuk leader) sudah tulis → Leader commit
- Leader beritahu Follower untuk commit juga
- Leader response ke Client: "sukses"
Kenapa harus majority?
Cluster 5 node. Butuh 3 yang setuju (majority = N/2 + 1).
Kenapa ga semua? Karena kalau harus tunggu semua:
- 1 node lambat = seluruh cluster lambat
- 1 node mati = seluruh cluster stuck
Kenapa ga cuma 1? Karena:
- Data belum aman. Kalau satu-satunya node yang punya data itu mati, data hilang
Majority itu sweet spot: cukup banyak supaya data aman, cukup sedikit supaya ga stuck nunggu node lambat/mati.
Quorum Deep Dive
Quorum = jumlah minimum node yang harus setuju supaya keputusan valid.
| Cluster Size | Quorum | Toleransi Node Mati |
|---|---|---|
| 3 node | 2 | 1 node boleh mati |
| 5 node | 3 | 2 node boleh mati |
| 7 node | 4 | 3 node boleh mati |
Perhatiin pattern-nya:
- Cluster ganjil lebih efisien. Cluster 4 node quorum-nya 3, toleransi mati 1 — sama kayak cluster 3 node. Mending 3 aja, hemat 1 server.
- Makin besar cluster, makin banyak toleransi gagal. Tapi juga makin banyak node yang harus koordinasi = overhead lebih besar
Itulah kenapa cluster biasanya 3 atau 5 node. 7+ jarang, kecuali beneran butuh fault tolerance tinggi.
Heartbeat dan Failure Detection
Gimana cluster tahu kalau ada node yang mati?
Heartbeat
Node secara berkala kirim sinyal "saya masih hidup" ke node lain. Ini disebut heartbeat.
sequenceDiagram
participant L as Leader
participant F1 as Follower 1
participant F2 as Follower 2
loop Setiap 100-200ms
L->>F1: Heartbeat
F1-->>L: Ack
L->>F2: Heartbeat
F2-->>L: Ack
end
Note over L,F2: Kalau follower ga ack, leader tandai suspect
Note over F1,F2: Kalau ga denger heartbeat, mulai election
Masalah: Slow vs Dead
Node ga response heartbeat. Dua kemungkinan:
- Mati beneran — harus failover
- Lambat aja — lagi GC pause, network congestion, CPU overload
Kalau terlalu cepat declare mati → false positive. Failover yang ga perlu. Disruptive.
Kalau terlalu lama nunggu → slow detection. Downtime lebih panjang.
Phi Accrual Failure Detector
Solusi yang lebih canggih dari sekadar "ga response dalam X detik = mati."
Idenya: track sejarah arrival time dari heartbeat. Hitung probability bahwa node sudah mati berdasarkan seberapa "telat" heartbeat terakhir dibanding pattern sebelumnya.
- Heartbeat biasanya datang tiap 100ms, tapi terakhir 500ms ga ada → phi naik, tapi belum tentu mati. Mungkin network spike.
- Heartbeat biasanya datang tiap 100ms, tapi terakhir 10 detik ga ada → phi sangat tinggi, kemungkinan besar mati.
Cassandra dan Akka pakai pendekatan ini. Lebih adaptive dan mengurangi false positives dibanding threshold statis.
Cluster di Real World
Redis Cluster
Redis Cluster membagi data ke beberapa node pakai hash slots (16384 slots total).
graph TB
subgraph Redis Cluster
N1["Node 1<br/>Slot 0-5460"]
N2["Node 2<br/>Slot 5461-10922"]
N3["Node 3<br/>Slot 10923-16383"]
R1["Replica 1<br/>(backup Node 1)"]
R2["Replica 2<br/>(backup Node 2)"]
R3["Replica 3<br/>(backup Node 3)"]
end
N1 -.-> R1
N2 -.-> R2
N3 -.-> R3
- Key di-hash → tentuin masuk slot mana → tentuin node mana yang handle
- Setiap node punya replica sebagai backup
- Node mati → replica di-promote → cluster tetap jalan
- Minimum 3 master nodes, biasanya 3 master + 3 replica = 6 node
PostgreSQL + Patroni
PostgreSQL sendiri ga punya built-in clustering. Patroni itu tool yang nambahin:
- Leader election pakai distributed consensus (etcd/ZooKeeper/Consul sebagai DCS)
- Automatic failover — primary mati, Patroni promote replica terbaru
- Configuration management — sync konfigurasi ke semua node
graph TB
subgraph Patroni Cluster
P1["PostgreSQL 1<br/>(Primary)"]
P2["PostgreSQL 2<br/>(Replica)"]
P3["PostgreSQL 3<br/>(Replica)"]
end
etcd[(etcd cluster<br/>DCS)]
P1 --> etcd
P2 --> etcd
P3 --> etcd
P1 -.->|streaming replication| P2
P1 -.->|streaming replication| P3
etcd menyimpan state cluster — siapa primary, siapa replica. Patroni terus monitor dan otomatis failover kalau primary hilang.
Kafka Cluster
Kafka pakai clustering untuk distributed message streaming.
- Broker: satu node Kafka. Cluster = sekelompok broker
- Topic: dibagi ke partitions, setiap partition ada di broker berbeda
- Replication factor: setiap partition di-replicate ke beberapa broker
graph TB
subgraph Kafka Cluster
B1["Broker 1<br/>Partition 0 (Leader)<br/>Partition 2 (Follower)"]
B2["Broker 2<br/>Partition 1 (Leader)<br/>Partition 0 (Follower)"]
B3["Broker 3<br/>Partition 2 (Leader)<br/>Partition 1 (Follower)"]
end
Producer --> B1
Producer --> B2
Producer --> B3
Setiap partition punya satu Leader broker dan beberapa Follower broker. Producer/Consumer selalu bicara ke Leader. Kalau Leader mati, salah satu Follower di-promote.
Sejak Kafka 3.x, Kafka pakai KRaft (Kafka Raft) — implementation mereka sendiri dari Raft consensus buat gantiin dependency ke ZooKeeper.
Common Pitfalls
1. Cluster size yang salah
- 2 node cluster: ga bisa quorum kalau 1 mati (1 dari 2 bukan majority). Praktis ga berguna buat HA
- Genap node: 4 node quorum = 3, toleransi mati 1. Sama kayak 3 node. Buang 1 server
- Terlalu banyak node: 15 node cluster → setiap write harus ke-replicate ke 8+ node minimum. Overhead gede, latency naik
2. Network partition ga di-test
Di lab, semua node bisa saling komunikasi. Di production, network partition terjadi. Kalau ga di-test:
- Split brain yang ga ke-detect
- Data divergence
- Cluster ga bisa re-converge setelah partition heal
3. Ga understand consistency model
Cluster yang bilang "CP" berarti ada kalanya request ditolak demi konsistensi. Kalau app kamu ga handle rejection dengan baik, user kena error.
Cluster yang bilang "AP" berarti ada kalanya data stale. Kalau app kamu expect data selalu fresh, bakal ada bug subtle.
Pahami consistency model cluster yang kamu pakai, dan tulis kode yang sesuai.
Ringkasan
| Konsep | Penjelasan |
|---|---|
| Cluster | Sekelompok server yang bekerja sebagai satu unit |
| HA Cluster | Fokus uptime, failover otomatis |
| LB Cluster | Fokus distribusi beban, semua node aktif |
| Storage Cluster | Fokus data redundancy dan distribusi |
| Shared-Nothing | Tiap node punya resource sendiri, komunikasi lewat network |
| Shared-Disk | Semua node akses storage yang sama |
| Leader Election | Proses milih satu node jadi koordinator |
| Raft | Consensus algorithm: Follower → Candidate → Leader |
| Quorum | Majority node harus setuju supaya keputusan valid |
| Heartbeat | Sinyal berkala untuk detect node yang mati |
Kesimpulan
Clustering itu fondasi dari hampir semua sistem terdistribusi modern. Mau itu database, message queue, cache, atau container orchestration — semuanya butuh clustering.
Yang paling penting dari catatan ini:
- Cluster bukan cuma "banyak server" — ada koordinasi, consensus, dan leader election di baliknya
- Quorum dan majority itu kunci — makanya cluster biasanya ganjil (3 atau 5 node)
- Failure detection itu ga gampang — bedain "mati" sama "lambat" itu challenging
- Consistency vs availability tetep jadi trade-off fundamental
- Raft itu consensus algorithm yang paling perlu dipahami — dipake di etcd, Consul, Kafka KRaft, dan banyak lagi
Clustering bikin sistem lebih reliable, tapi juga nambah complexity. Sebelum kluster-kan semuanya, tanyain dulu: beneran butuh, atau satu server yang kuat udah cukup?
Karena cluster yang salah di-manage bisa jadi lebih fragile daripada satu server yang di-manage dengan bener.
