Consensus & Distributed Agreement — System Design

Di kebanyakan sistem terdistribusi, beberapa node harus sepakat tentang satu nilai — siapa leader, urutan transaksi, atau isi config. Masalah ini bernama…

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:

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

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:

  1. Jadi candidate, menaikkan term (1 jadi 2), dan memilih dirinya sendiri.
  2. Mengirim RequestVote ke semua node.
  3. Tiap node memberi satu suara per term, ke candidate pertama yang meminta, dan hanya kalau log candidate itu minimal sama barunya dengan log miliknya.
  4. 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

🎯 Kapan pakai consensus

Consensus lambat dibanding operasi lokal: tiap write menunggu mayoritas node. Pakai untuk state yang kecil tapi kritis:

Data bervolume besar (log klik, sesi login) tetap di database atau cache biasa.

⚠️ Jebakan yang sering ketemu

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.

Yang akan kamu pelajari