Consensus adalah cara beberapa server (disebut node) sepakat tentang satu hal, misalnya urutan perubahan data atau siapa pemimpinnya, walau sebagian node mati atau jaringannya putus. Bayangin panitia lima orang yang mencatat penjualan kursi konser, masing-masing di bukunya sendiri. Ketua membacakan keputusan, "kursi A-12 untuk Budi", dan keputusan itu sah begitu minimal tiga dari lima sudah mencatatnya. Kalau ketua menghilang, sisanya memilih ketua baru, dan yang menang harus dapat suara terbanyak.
🧪 Tebakan cepat: jaringan putus. n1 (leader) dan n2 di satu sisi, n3, n4, n5 di sisi lain. n1 menerima "A-14 = dewi" dan menyalinnya ke n2. Apakah kursi A-14 resmi milik dewi? Tebak dulu, jawabannya ada di bagian "Partition: leader lama di sisi minoritas".
Kenapa butuh consensus
Di lesson Kenapa Distributed System Sulit, split brain terjadi saat dua node sama-sama merasa jadi leader, lalu kursi yang sama terjual ke dua orang. Consensus mencegahnya dengan satu aturan: keputusan baru sah kalau disetujui mayoritas node. Dua kelompok yang terpisah gak mungkin sama-sama punya mayoritas, jadi cuma satu sisi yang bisa memutuskan.
Algoritma consensus yang paling banyak dipakai sekarang adalah Raft, yang sengaja dirancang supaya mudah dipahami. Lab-nya menjalankan Raft yang disederhanakan untuk register kursi TiketNada: lima node, n1 sampai n5, dan tiap entry di log adalah satu keputusan kursi seperti A-12 = budi.
Raft: leader, follower, candidate, term
Tiap node punya satu peran:
- Leader: satu-satunya yang menerima write dari client, lalu menyalinnya ke node lain.
- Follower: pasif, menerima salinan dari leader dan menjawab permintaan suara.
- Candidate: follower yang sedang mencalonkan diri jadi leader.
Term adalah nomor periode jabatan. Tiap pemilihan menaikkan term satu. Di awal Lab, n1 adalah leader term 1. Leader mengirim heartbeat (di model ini tiap 50 ms) supaya follower tahu dia masih hidup. Node yang melihat term lebih tinggi dari miliknya langsung ikut term itu dan jadi follower, termasuk leader lama.
Log replication: commit setelah mayoritas
Client menulis lewat leader. Leader menambah entry ke log-nya, lalu mengirim AppendEntries (pesan "simpan entry ini") ke semua follower. Entry baru commit (resmi, gak akan hilang) begitu mayoritas node menyimpannya. Leader ikut dihitung.
| ms | Kejadian |
|---|---|
| 0 | client minta A-13 = siti ke n1 |
| 0 | n1 menambah entry #2 ke log-nya, belum commit |
| 2 | n2, n3, n4, n5 menyimpan dan menjawab ack: 5 dari 5 |
| 2 | mayoritas tercapai: commit, client dapat OK |
Leader gak perlu menunggu semua node. Di cluster 5 node, 3 node yang menyimpan (leader + 2 follower) sudah cukup untuk commit, jadi 2 node yang lambat atau mati gak menghentikan sistem.
Mayoritas dan quorum
Jumlah suara minimal yang dibutuhkan disebut quorum. Untuk consensus, quorum adalah mayoritas mutlak: lebih dari separuh. Rumusnya Math.floor(N / 2) + 1, atau sama saja, jumlah setuju > N / 2.
| Ukuran cluster | Quorum | Boleh mati |
|---|---|---|
| 3 | 2 | 1 |
| 4 | 3 | 1 |
| 5 | 3 | 2 |
| 7 | 4 | 3 |
Latihannya membuat dua function untuk aturan ini:
function hasQuorum(votes) {
const yes = votes.filter(Boolean).length; // hitung yang true
return yes > votes.length / 2;
}
function canCommit(clusterSize, yesVotes) {
return yesVotes > clusterSize / 2;
}
console.log(hasQuorum([true, true, true, false, false])); // true: 3 > 2,5
console.log(canCommit(4, 2)); // false: 2 bukan lebih dari 2
votes.filter(Boolean)menyisakan elemen yangtrue, jadi.length-nya jumlah suara setuju.- Pakai
>, bukan>=. Separuh persis bukan mayoritas:canCommit(4, 2)harusfalse, sedangkancanCommit(4, 3)true. - Tanpa satu pun
true,yesbernilai 0, dan0 > 2,5itufalse.
Cluster 4 node gak lebih tahan dari 3 node: dua-duanya cuma boleh kehilangan 1. Lebih buruk lagi, 4 node yang terbelah 2 dan 2 gak punya mayoritas di sisi mana pun, jadi seluruh cluster berhenti menerima write. Makanya cluster consensus dibuat ganjil: 3, 5, atau 7.
Leader election
Follower yang gak menerima heartbeat selama election timeout menganggap leader-nya mati. Di Raft, timeout ini diacak antara 150 dan 300 ms supaya node gak mencalonkan diri bersamaan. Di Lab tiap node punya angka tetap: n5 180 ms, n3 210, n1 250, n4 270, n2 290. Lalu follower itu:
- Jadi candidate, menaikkan term (1 jadi 2), dan memilih dirinya sendiri.
- Mengirim RequestVote ke semua node.
- Tiap node memberi satu suara per term, ke candidate pertama yang meminta, dan hanya kalau log candidate itu minimal sama barunya dengan log miliknya.
- Dapat mayoritas (3 dari 5)? Jadi leader, lalu langsung mengirim heartbeat.
Matikan n1 di Lab, lalu tunggu: setelah 180 ms n5 jadi candidate term 2 dan mendapat suara n2, n3, n4. Dengan dirinya sendiri, 4 dari 5: n5 leader term 2. Gak ada node yang langsung jadi leader tanpa suara, dan itu yang mencegah dua leader di term yang sama.
Partition: leader lama di sisi minoritas
Ini urutan yang bisa kamu jalankan di Lab: putus jaringan, tulis lewat n1, tunggu election timeout, tulis lewat n5, lalu sambungkan lagi.
| ms | Sisi n1, n2 |
Sisi n3, n4, n5 |
|---|---|---|
| 5 | n1 menulis A-14 = dewi, disimpan 2 dari 5: belum commit |
|
| 185 | gak ada heartbeat: n5 jadi candidate term 2, dapat 3 suara, jadi leader |
|
| 187 | n5 menulis A-14 = maya, disimpan 3 dari 5: commit |
|
| 237 | jaringan pulih: n1 melihat term 2, turun jadi follower, membuang A-14 = dewi dan menyalin log n5 |
Jadi A-14 bukan milik dewi. Entry-nya cuma sampai ke 2 node, gak pernah commit, dan client-nya gak pernah dapat OK. Itu jawaban tebakannya. Hanya sisi yang punya mayoritas (3 dari 5) yang bisa memilih leader dan commit. Sisi minoritas berhenti menerima write: konsistensi dijaga dengan mengorbankan ketersediaan di sisi itu. Itu sisi "CP" di lesson CAP Theorem.
📌 Paxos, ZAB, dan sistem yang memakai consensus
- Paxos (Leslie Lamport) adalah algoritma consensus yang lebih tua dan lebih umum, tapi terkenal sulit dipahami dan diimplementasikan dengan benar. Raft lahir untuk menjawab itu.
- ZooKeeper memakai ZAB, keluarga dekat Paxos. etcd (penyimpan state Kubernetes) dan Consul memakai Raft. Database terdistribusi seperti CockroachDB dan TiDB memakai Raft per potongan data.
- Ada bukti teori (FLP, 1985) bahwa di jaringan yang bisa menunda pesan tanpa batas, gak ada algoritma yang selalu bisa mencapai kesepakatan. Raft tetap aman (gak pernah dua keputusan berbeda), dan dalam praktik selesai karena timeout-nya acak dan jaringan akhirnya menyampaikan pesan.
- Jangan menulis Raft sendiri untuk production. Pakai etcd, Consul, atau ZooKeeper.
🎯 Kapan pakai consensus
Consensus lambat dibanding operasi lokal: tiap write menunggu mayoritas node. Pakai untuk state yang kecil tapi kritis:
- Leader election dan lock: cuma satu server yang boleh menjalankan job "tutup penjualan jam 23.59".
- Config: harga dan pengaturan yang harus sama di semua server.
- Service discovery: daftar server yang sedang hidup.
Data bervolume besar (log klik, sesi login) tetap di database atau cache biasa.
⚠️ Jebakan yang sering ketemu
- Cluster genap. 4 node gak lebih tahan dari 3, dan bisa terbelah 2 dan 2 tanpa mayoritas.
>=di latihan. Separuh persis bukan mayoritas:canCommit(4, 2)harusfalse. Pakai>.- Lupa leader ikut dihitung. Di cluster 5 node, leader ditambah 2 follower sudah 3: cukup untuk commit.
- Consensus untuk semua data. Tiap write menunggu mayoritas node, jadi pakai hanya untuk state kritis yang kecil.
TL;DR: Consensus membuat beberapa node sepakat walau sebagian mati atau jaringan putus. Di Raft, satu leader menerima write dan menyalinnya ke follower lewat AppendEntries; entry commit begitu mayoritas node menyimpannya, leader ikut dihitung. Quorum = mayoritas mutlak, Math.floor(N / 2) + 1 atau setuju > N / 2: cluster 5 node butuh 3 dan tahan 2 node mati, dan separuh persis (2 dari 4) bukan mayoritas. Follower tanpa heartbeat selama election timeout (acak 150 sampai 300 ms) jadi candidate, menaikkan term, meminta suara, dan jadi leader kalau dapat mayoritas; tiap node memberi satu suara per term. Saat jaringan terbelah, cuma sisi mayoritas yang bisa memilih leader dan commit; write di leader lama di sisi minoritas gak pernah commit dan dibuang saat jaringan pulih. Pakai cluster ganjil, pakai etcd, Consul, atau ZooKeeper, dan simpan cuma state kecil yang kritis.