Skip to content

Change Data Capture: Menangkap Setiap Perubahan Data secara Real-Time ​

Bayangkan aplikasi e-commerce yang menyimpan data produk di PostgreSQL. Data yang sama ternyata dibutuhkan di banyak tempat lain:

  • Elasticsearch untuk fitur pencarian produk.
  • Redis sebagai cache katalog yang aksesnya cepat.
  • Data warehouse untuk dashboard analytics tim business.
  • Service notifikasi yang mengirim email ketika harga berubah.

Cara paling intuitif menyinkronkannya: setiap kali aplikasi selesai menulis ke database, aplikasi juga mengirim event ke Kafka dan mengupdate Elasticsearch. Pola ini disebut dual write, dan di sinilah masalah dimulai.

text
Aplikasi: BEGIN -> UPDATE produk -> COMMIT (sukses)
Aplikasi: kirim event "produk berubah" ke Kafka (gagal: network error)

Database sudah berisi harga baru, tetapi Elasticsearch masih menyimpan harga lama. Tidak ada mekanisme yang menjamin kedua tulisan itu sukses bersama, karena dua sistem yang berbeda tidak berada dalam satu transaction. Inkonsistensi seperti ini biasanya baru ketahuan ketika customer komplain hasil pencarian tidak sesuai.

Change Data Capture (CDC) menyelesaikan masalah ini dengan membalik arahnya: jangan biarkan aplikasi menyinkronkan sistem lain secara manual. Ambil perubahan langsung dari sumber kebenarannya, yaitu database.

Apa itu CDC? ​

Change Data Capture adalah pola untuk menangkap setiap perubahan data di database, baik INSERT, UPDATE, maupun DELETE, lalu mengalirkannya sebagai event yang bisa dikonsumsi oleh sistem lain, hampir secara real-time.

Tiga karakteristik inti CDC:

  • Database tetap satu-satunya sumber kebenaran (source of truth). Sistem lain tidak lagi menulis salinan data secara mandiri, melainkan mengikuti aliran perubahan dari database.
  • Setiap perubahan menjadi event, termasuk DELETE yang justru paling sering terlewat oleh pendekatan polling sederhana.
  • Aliran berjalan otomatis, tanpa perlu mengubah setiap code path yang menulis ke database. Hanya ada satu penambahan infrastruktur, bukan perubahan di puluhan service.

Konsep Dasar: dari mana perubahan ditangkap? ​

CDC bisa diimplementasikan dengan beberapa cara. Perbedaannya penting karena menentukan keandalan dan beban sistem.

Query-based CDC (polling) ​

Cara paling sederhana: sebuah job berjalan berkala dan mencari data yang berubah sejak eksekusi terakhir:

sql
SELECT *
FROM products
WHERE updated_at > :last_check
ORDER BY updated_at;

Cara ini mudah dipahami dan tidak butuh tool tambahan, tetapi punya kelemahan mendasar:

  • DELETE tidak terlihat: baris yang sudah dihapus tidak muncul di hasil query, jadi sistem lain tidak tahu produk tersebut sudah tidak ada.
  • Latency sebesar interval polling: kalau job berjalan tiap 1 menit, data terbaru datang hingga 1 menit terlambat.
  • Butuh kolom updated_at yang dipelihara konsisten di semua tabel, yang sering dilupakan di kode yang lama.
  • Query berulang menambah beban ke database yang sama dengan aplikasi.

Trigger-based CDC ​

Database trigger mendengarkan setiap perubahan dan menulis rekamannya ke tabel khusus, lalu proses lain membaca tabel itu. Cara ini menangkap DELETE dan lebih tepat waktu, tetapi trigger menambah beban di dalam database dan sering luput dari pemeliharaan skema.

Log-based CDC ​

Cara yang paling efisien: ambil perubahan langsung dari log perubahan yang database tulis secara alami, yaitu WAL di PostgreSQL atau redo log di MySQL InnoDB.

Bacaan lanjutan

WAL adalah log append-only yang database tulis ke disk untuk setiap perubahan sebagai jaminan durability. Untuk memahami cara kerjanya, termasuk kenapa tulisan ke log ini cepat dan bagaimana hubungannya dengan COMMIT, baca article Write-Ahead Log: Kenapa Database Menulis Dua Kali tapi Tetap Cepat.

Log-based CDC bekerja dengan prinsip sederhana: database sudah mencatat setiap perubahan di WAL, tinggal dibaca ulang. Tidak ada query berulang, tidak ada trigger tambahan, tidak ada kolom updated_at yang harus dipelihara. Karena inilah hampir semua tool CDC modern, seperti Debezium, memakai pendekatan ini.

Loading diagram...

Bagaimana log-based CDC bekerja? ​

Alur lengkapnya, per komponen:

  1. Aplikasi menulis seperti biasa. Tidak ada perubahan di kode aplikasi sama sekali. Tulisan ke database tetap menghasilkan record WAL, persis seperti biasanya.
  2. CDC connector membaca log. Tool seperti Debezium menghubungkan diri ke database sebagai client replikasi. Di PostgreSQL, ini bekerja lewat logical replication slot, mekanisme bawaan yang memungkinkan client menerima aliran perubahan secara berurutan tanpa mengganggu operasi database.
  3. Perubahan diubah menjadi event yang seragam. Satu perubahan satu baris menjadi satu event JSON yang berisi sebelum dan sesudahnya: { "before": { "price": 100000 }, "after": { "price": 120000 }, "op": "u" }. Nilai op menjelaskan jenisnya: c (create), u (update), atau d (delete).
  4. Event dikirim ke message broker. Kafka biasanya menjadi perantara, lalu setiap sistem lain (search index, cache, warehouse) menjadi consumer yang masing-masing berlangganan topiknya sendiri.

Dua konsep yang penting dipahami di sini:

  • Initial snapshot: aliran WAL hanya memuat perubahan mulai saat connector berjalan. Untuk data yang sudah ada sebelumnya, connector menjalankan initial snapshot, yaitu membaca seluruh isi tabel satu kali di awal, sebelum mulai mengikuti aliran perubahan.
  • Offset (posisi log): connector mencatat posisi terakhir yang sudah dibaca di WAL. Jika connector mati dan hidup kembali, dia melanjutkan dari posisi itu, bukan mengulang dari awal. Inilah yang membuat CDC andal dan tidak kehilangan event.

Kenapa CDC lebih andal daripada dual write? ​

Perbedaan mendasarnya ada di jumlah penulis:

  • Pada dual write, banyak titik yang bisa gagal secara terpisah: database sukses tapi broker gagal, atau aplikasi crash di antara dua tulisan. Tidak ada yang memastikan keduanya konsisten.
  • Pada CDC, database adalah satu-satunya sumber, dan event dipancing dari log yang sudah dijamin durability oleh database itu sendiri. Kalau perubahan data sudah di-COMMIT, event-nya pasti bisa dipancarkan. Kalau transaksi di-rollback, WAL tidak menghasilkan event, dan tidak ada sistem lain yang tahu-menahu tentang perubahan itu.

Konsistensi antar sistem tidak lagi dijaga oleh kode aplikasi, melainkan oleh arsitektur.

Kapan CDC dipakai di pekerjaan? ​

CDC cocok untuk kebutuhan seperti ini:

  • Sinkronisasi real-time database ke search index atau cache.
  • Mengalirkan perubahan ke data warehouse atau stream processing tanpa batch export berkala.
  • Membangun event-driven architecture dari database yang sudah ada, tanpa mengubah kode aplikasi.
  • Audit log: mencatat siapa mengubah apa, termasuk DELETE.

Sebaliknya, jangan pakai CDC kalau kebutuhannya sederhana: untuk memvalidasi data antar sistem sekali sehari atau menjalankan report berkala, polling sederhana atau query langsung sudah cukup dan jauh lebih murah dioperasikan.

Perhatian operasional

Connector log-based CDC membaca dari replication slot. Kalau connector mati dalam waktu lama dan slot tidak dipantau, WAL akan menumpuk karena database tidak berani membersihkan log yang belum dibaca, dan disk database bisa penuh. Pantau lag konsumsi dan ukuran slot di monitoring.

Rangkuman ​

  • CDC menangkap setiap perubahan data (INSERT, UPDATE, DELETE) dari database dan mengalirkannya sebagai event ke sistem lain, hampir real-time.
  • Pendekatan polling (query-based) sederhana tetapi melewatkan DELETE dan menambah beban query. Log-based CDC adalah pendekatan yang paling efisien.
  • Log-based CDC membaca ulang WAL atau redo log yang database sudah tulis secara alami, lalu mengubahnya menjadi event seragam dan mengirimkannya ke message broker.
  • Initial snapshot menyalin data yang sudah ada di awal, dan offset memastikan connector melanjutkan dari posisi terakhir saat hidup kembali.
  • CDC menghilangkan masalah dual write: database tetap satu-satunya sumber kebenaran, dan konsistensi antar sistem dijaga oleh arsitektur, bukan kode aplikasi.

References ​