← semua materi
05:00 Arsitektur Β· 29 Oct 2026 Β· 05:02

πŸ“š Topik β€” Consistency Models: Strong, Eventual, Read-Your-Writes Kategori: Distributed Systems Β· Level: advanced Β· Sesi 05:00 Deep Learning


🎯 Tujuan Belajar

Setelah sesi ini, keputusan berikut jadi lebih baik:

  1. Bisa memilih consistency level per-operasi, bukan per-database. Satu sistem biasanya butuh model berbeda di jalur berbeda (saldo vs feed komentar).
  2. Bisa membaca dokumentasi database dan tahu apa yang sebenarnya dijanjikan β€” "strong consistency" di marketing sheet hampir selalu lebih lemah dari yang dibayangkan.
  3. Bisa mendiagnosis bug anomali yang muncul sekali sebulan di production ("kok komentar saya hilang lalu muncul lagi?") sebagai masalah konsistensi, bukan "bug random".
  4. Bisa menolak permintaan "pokoknya harus konsisten" dengan biaya nyata: latency, availability, throughput.

🧠 Penjelasan Inti

Masalah yang diselesaikan

Begitu data ada di lebih dari satu node, muncul pertanyaan: kalau saya baca dari node A sekarang, apakah saya melihat tulisan yang barusan masuk ke node B?

Tanpa replikasi, tidak ada masalah. Dengan replikasi, ada tiga sumber anomali:

Consistency model = kontrak antara sistem dan klien tentang nilai apa yang mungkin dikembalikan. Bukan jaminan "data benar", tapi jaminan "data yang kamu lihat termasuk himpunan hasil yang legal".

Empat level praktis yang perlu dihafal

Dari kuat ke lemah (bukan tangga linear β€” ini bukan skala satu dimensi, lihat bagian miskonsepsi):

Model Jaminan Biaya
Linearizability (strong) Setiap operasi tampak atomik & instan pada satu titik waktu global. Real-time ordering dihormati. Koordinasi lintas node per-operasi. Latency β‰ˆ slowest quorum member. Tidak tersedia saat partition.
Sequential consistency Semua node melihat urutan operasi yang sama, tapi urutan itu tidak harus sesuai waktu real. Butuh total order; tanpa batasan real-time.
Causal consistency Operasi yang berhubungan sebab-akibat dilihat semua node dalam urutan sama. Operasi konkuren boleh beda urutan. Butuh tracking dependency (vector clock / versi). Tersedia saat partition.
Eventual consistency Kalau tidak ada write baru, semua replica akhirnya konvergen. Tanpa batas waktu. Paling murah, paling tersedia. Klien bisa lihat apa saja di jendela antara.

Read-your-writes (RYW) bukan level, tapi session guarantee β€” property yang dijamin untuk satu klien sepanjang sesinya. Klien yang menulis nilai X akan selalu membaca X atau lebih baru. Ini biasanya yang sebenarnya dibutuhkan user, dan jauh lebih murah daripada linearizability.

Session guarantees lain yang sering satu paket (dari sesi Vogels 2009, "Eventually Consistent", CACM):


βš™οΈ Cara Kerja Internal

1. Bagaimana "strong" diimplementasikan

Tiga mekanisme dominan:

(a) Single-leader + synchronous replication. Semua write ke leader; leader tunggu ACK dari follower (atau quorum) sebelum balas klien. Read dari leader = linearizable. Ini model PostgreSQL synchronous_commit=on dengan synchronous_standby_names, MySQL semi-sync.

Catatan penting: read dari follower tetap tidak linearizable meski replikasi sinkron, karena follower bisa saja belum apply β€” kecuali replikasi sinkron berarti "apply", bukan "received WAL". Di PostgreSQL, synchronous_commit=remote_apply yang memberi jaminan itu; remote_write hanya jaminan sampai OS follower, bukan apply.

(b) Quorum (R + W > N). Cassandra/Dynamo-style. Kalau W + R > N, read set dan write set pasti beririsan β†’ read melihat write terakhir. Contoh N=3, W=2, R=2 β†’ 2+2 > 3 βœ“. Tapi ada lubang besar: quorum memberi strong-ish, bukan linearizable, karena tidak ada jaminan urutan antar-quorum (dua write konkuren bisa "menang" di quorum berbeda β€” ini yang disebut quorum inconsistency / "sloppy quorum"). Cassandra menyebut level QUORUM/LOCAL_QUORUM; klaim linearizable-nya butuh lightweight transactions (Paxos) atau leader-only read.

(c) Konsensus (Raft/Paxos) + clock uncertainty. etcd, Consul, CockroachDB, Spanner. Spanner menambahkan TrueTime: interval ketidakpastian jam (Ξ΅, orde milidetik β€” angka pastinya bergantung deployment dan commit-wait, jangan hafal satu angka) dan commit-wait supaya timestamp commit pasti sudah lewat di semua node. Ini yang membuatnya externally consistent (linearizable) lintas region β€” dengan biaya write latency = 2Ξ΅ + round-trip.

2. Bagaimana "eventual" diimplementasikan & kenapa bisa konvergen

Konvergensi butuh aturan resolusi konflik yang deterministik dan komutatif/idempoten:

3. Bagaimana RYW diimplementasikan (murah, ini kuncinya)

Empat teknik, dari paling murah:

  1. Sticky routing / session affinity β€” klien selalu ke node yang sama. Murah, rapuh (node mati = jaminan hilang).
  2. Read-from-leader setelah write β€” tandai sesi "kotor" selama T detik; semua read ke leader. Implementasi di aplikasi, bukan DB.
  3. Version/lag token β€” server balas X-Min-Version: 41235; klien kirim balik; replica nolak read kalau belum sampai versi itu (atau tunggu sebentar). Ini yang dipakai banyak sistem: read-your-writes tanpa memaksa semua read ke leader.
  4. Monotonic read via sticky timestamp β€” klien bawa timestamp read terakhir, replica yang lebih muda menolak.

Teknik 3 dan 4 memberi RYW dengan biaya mendekati nol di steady state β€” inilah kenapa "konsisten" jarang butuh full linearizability.


πŸ—οΈ Diagram Alur

Write path (leader + async replica, RYW via token):

client ──write──► leader ──ACK v=101──► client
                    β”‚
                    └──async log──► replica (v=99 saat ini)

client ──read (+ header "min-version: 101")──► replica
                                                β”‚
                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                   v>=101?                          v<101?
                        β”‚                                β”‚
                   serve read                  wait ≀ N ms, else
                                               ──► route ke leader
                                               atau return 503/retry
Quorum overlap (N=3, W=2, R=2):

   W set {A,B}      R set {B,C}
        β”‚                β”‚
        └──── B β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   ← irisan menjamin read melihat write
Partition (CAP dalam praktik, N=3):

  [A,B] β”€β”€βœ‚β”€β”€ [C]
   β”‚            β”‚
   mayoritas    minoritas
   tetap write  ?  β†’ CP: tolak write
                  β†’ AP: terima write, konflik nanti

βš–οΈ Trade-off & Kapan JANGAN Dipakai

Ini bagian yang menentukan senior vs junior.

Kapan JANGAN pakai strong consistency (linearizability)

Kapan WAJIB strong(ish)

Biaya yang sering dilupakan

Pilihan Latency Availability Kompleksitas aplikasi
Linearizable Tinggi (quorum/leader RTT) Turun saat partition (CP) Rendah β€” "anggap satu DB"
Causal Sedang Tinggi Sedang β€” butuh dependency tracking
Eventual Rendah Tinggi Tinggi β€” resolusi konflik, UI yang toleran, kompensasi
Eventual + RYW Rendah Tinggi Rendah-sedang β€” ini sweet spot paling umum

Poin yang sering luput: eventual consistency tidak menghilangkan biaya, ia memindahkannya ke aplikasi dan ke user. UI yang menampilkan "komentar kamu sedang diproses", job rekonsiliasi, tim customer service yang memperbaiki data. Itu biaya nyata, sering lebih besar dari biaya latency.

Jebakan "sesuaikan level per operasi" tanpa disiplin

Mencampur level di satu sistem membuat invariant tidak jelas. Kalau saldo dibaca eventually-consistent tapi dipakai untuk keputusan write strongly-consistent, kamu punya race. Aturan praktis: tentukan invariant dulu, lalu turunkan level per operasi β€” jangan sebaliknya.


🏭 Contoh Produksi & Failure Mode

1. Read-your-writes hilang saat failover (pola paling umum). User update profil β†’ write ke leader β†’ leader mati β†’ replica promosi β†’ replika promosi tertinggal beberapa detik β†’ user refresh, melihat data lama, submit ulang. Muncul sebagai "data saya kembali sendiri". Mitigasi: version token, atau read-from-leader sampai replikasi terkonfirmasi.

2. LWW membuang update (silent data loss). Dua device update field berbeda di record sama; timestamp device lebih cepat menang; field lain hilang. Ini failure mode klasik sync mobile. Mitigasi: per-field LWW (bukan per-record), atau CRDT map.

3. Quorum "cukup" tapi tidak linearizable. Cassandra QUORUM read + write pada dua write konkuren bisa menghasilkan kedua klien sama-sama "berhasil" dengan nilai berbeda. Bukan bug β€” itu definisi quorum tanpa consensus. Kalau butuh compare-and-set, pakai LWT (Paxos) dan terima biayanya (4 round-trip).

4. Stale read menyebabkan write invalid. Baca kuota dari replica (masih 1 tersisa), dua request paralel sama-sama lolos cek, kuota jadi -1. Ini bukan masalah konsistensi database saja β€” ini check-then-act lintas replica. Solusi: atomic conditional write di leader (UPDATE ... WHERE kuota > 0), bukan baca-lalu-tulis.

5. Monotonic reads dilanggar oleh load balancer. Round-robin ke 3 replica dengan lag berbeda β†’ user melihat komentar, refresh, komentar hilang, refresh, muncul lagi. Terlihat seperti "ghost data". Mitigasi: sticky per-sesi atau lag-aware routing.

6. Split-brain dengan dua leader (bukan CP, bukan AP β€” rusak). Failover prematur / unhealthy threshold terlalu agresif β†’ dua node sama-sama menganggap diri leader β†’ divergen write. Redis Sentinel, Patroni, dan MySQL Group Replication semuanya pernah punya insiden kelas ini. Ini alasan fencing token / STONITH ada.


⚠️ Miskonsepsi Umum

  1. "CAP = pilih 2 dari 3." Salah secara operasional. P adalah kondisi yang terjadi, bukan pilihan. Saat partition, kamu memilih C atau A per operasi. Saat tidak ada partition, kamu memilih latency vs consistency β€” itulah yang PACELC tambahkan (If Partition then A or C, Else L or C). Model mental yang lebih akurat: CAP adalah tentang perilaku saat gagal, PACELC tentang biaya saat normal.

  2. "Eventual consistency = tidak konsisten / tidak ada jaminan." Eventual adalah jaminan nyata (konvergensi, asalkan tidak ada write baru dan anti-entropy jalan). Yang tidak dijamin adalah kapan dan urutan antara. Sistem yang mendesain eventual dengan CRDT punya jaminan lebih kuat dari "mungkin benar" β€” mereka punya strong eventual consistency (konvergen deterministik).

  3. "Konsisten = benar." Consistency model tidak menjamin data sesuai realitas, hanya jaminan tentang apa yang mungkin dilihat. Bug aplikasi yang menulis nilai salah tetap konsisten sempurna.

  4. "Pakai strongly consistent di semua tempat itu aman." Aman secara kebenaran, tapi menciptakan coupling: satu region down = semua read down. Banyak outage besar adalah hasil terlalu banyak strong read, bukan terlalu sedikit.

  5. "Cache bukan bagian dari masalah konsistensi." Cache adalah replica. Semua model konsistensi berlaku untuk Redis dan CDN juga β€” cache invalidation adalah masalah konsistensi terdistribusi dengan nama lain.

  6. "Kalau pakai Postgres, semua otomatis konsisten." Read replica, connection pooler dengan routing, dan multi-region read semua memperkenalkan jaminan yang lebih lemah. synchronous_commit=off + read replica = eventual, walau DB-nya "SQL".


βœ… Cek Pemahaman

  1. Sistem pakai N=3, W=1, R=3. Apakah read linearizable? Apakah write durable? Apa yang terjadi kalau node yang menerima write mati sebelum replikasi?
  2. Kamu punya endpoint POST /orders lalu GET /orders/:id. Desain mekanisme RYW minimum yang tidak memaksa semua GET ke leader. Versi mana yang kamu kirim ke klien, dan apa yang terjadi kalau replica tersebut mati?
  3. Tim minta "eventual consistency supaya cepat" untuk fitur saldo e-wallet. Sebutkan dua invariant yang rusak, dan skema apa yang sebenarnya kamu usulkan.

πŸ”‘ Poin Kunci


➑️ Eksplorasi Lanjut