Masalah dan Cakupan
Sebuah perusahaan memiliki 20 database PostgreSQL OLTP, 200 tabel untuk disinkronkan, dan 8 TB data saat ini. Sumber menghasilkan rata-rata 20.000 perubahan baris ter-commit per detik dan 60.000 pada saat peak. Rata-rata perubahan terenkode berukuran sekitar 1 KB. Data harus mencapai warehouse analitis atau lakehouse, dengan latensi p99 dari commit transaksi sumber hingga data terkurasi yang dapat di-query di bawah dua menit. Sinkronisasi awal harus selesai dalam 72 jam tanpa menghentikan proses write aplikasi, dan beban kerja snapshot ditambah CDC harus menyebabkan regresi p99 write sumber kurang dari 5%.
Pipeline harus menangani insert, update, delete, dan perubahan nilai primary key. Pipeline harus mempertahankan urutan perubahan untuk suatu baris dalam satu sumber, menggunakan pengiriman at-least-once, mendukung evolusi skema dan replay berdasarkan tabel atau rentang primary key, memulihkan diri dari kegagalan sumber dan sink, serta menyediakan rekonsiliasi yang dapat membuktikan kebenaran (correctness). Stream perubahan yang durable menyimpan event mentah selama tujuh hari, sementara object store berbiaya lebih rendah menyimpan riwayat yang lebih lama. Jumlah database, throughput, ukuran, latensi, dan batasan sumber daya adalah asumsi wawancara, bukan jaminan performa untuk sebuah produk.
Meskipun desain ini berisi broker dan beberapa komponen, keahlian intinya adalah data engineering: menggabungkan snapshot tersimpan ke stream perubahan tanpa batas (unbounded) tanpa celah, mendefinisikan posisi yang dapat dipulihkan dan batasan idempoten, serta membuktikan bahwa tujuan tidak kehilangan data maupun salah secara diam-diam.
Hal yang Dievaluasi Pewawancara
Sinyal pertama adalah mendefinisikan correctness sebelum menggambar komponen. Jawaban yang lemah dimulai dengan “Debezium ditambah Kafka.” Jawaban yang kuat menyatakan invarian: perubahan yang telah di-commit tidak boleh hilang, satu baris harus konvergen sesuai urutan sumber, event yang di-replay tidak boleh mengubah status akhir, penghapusan harus sampai ke target, batas antara snapshot dan stream tidak boleh memiliki celah, dan posisi pemulihan yang tidak pasti harus fail-closed alih-alih melanjutkan secara diam-diam.
Sinyal kedua adalah memahami bahwa snapshot awal bukanlah “ekspor semua tabel, lalu aktifkan CDC.” Operasi write terus berjalan selama ekspor 8 TB. Jika penangkapan WAL baru dimulai setelah ekspor, perubahan perantara mungkin sudah hilang. Desain yang andal menetapkan posisi log yang dapat dipulihkan dan mekanisme retensi sebelum atau saat memperoleh snapshot yang konsisten, lalu melakukan streaming perubahan yang di-commit dari posisi yang sesuai. Sebuah konektor dapat mengenkapsulasi prosedur ini, tetapi kandidat tetap harus menjelaskan mengapa serah terima (handoff) tersebut tidak memiliki celah.
Sinyal ketiga adalah mempertahankan pengiriman at-least-once hingga ke sink. Konektor dapat mengalami crash setelah berhasil memancarkan event secara durable tetapi sebelum mencatat offset sumbernya. Sebuah batch warehouse dapat di-commit sementara acknowledgement-nya hilang. “Exactly once di dalam broker” tidak secara otomatis mencakup warehouse eksternal. Jawaban yang kuat menyertakan identitas sumber, posisi sumber, dan urutan transaksi ke setiap event, lalu menerapkan event hanya jika versinya lebih baru daripada versi yang sudah tercatat untuk baris tersebut.
Sinyal keempat adalah mengenali risiko dua sisi dari replication slot PostgreSQL. Slot memungkinkan konektor melanjutkan dari LSN, tetapi slot juga menahan WAL saat konektor tertinggal. Tanpa peringatan retained-byte dan headroom disk, pemadaman (outage) pada sink pada akhirnya dapat memenuhi penyimpanan sumber. Jika slot dihapus dan dibuat ulang, slot baru tidak dapat mereproduksi posisi lama. Pipeline harus berhenti, melakukan rekonsiliasi, atau membuat snapshot ulang alih-alih melanjutkan “mulai dari sekarang” dan mengklaim tidak ada yang hilang.
Terakhir, jawaban harus mencakup semantik data riil. Event penghapusan bisnis berbeda dari tombstone yang digunakan untuk pemadatan log (log compaction). Pembaruan nilai primary key umumnya muncul sebagai penghapusan untuk key lama dan pembuatan untuk key baru. LSN dari database yang berbeda tidak dapat dibandingkan. Jika konsumen membutuhkan visibilitas atomik untuk setiap baris dalam transaksi multi-baris, desain harus menggunakan metadata batas transaksi dan menerima buffering ekstra, latensi, serta kompleksitas pemulihan.
Pertanyaan Klarifikasi Sebelum Menjawab
- Apakah tujuan memerlukan status saat ini, riwayat perubahan lengkap, atau keduanya? Status saat ini cocok untuk operasi MERGE primary key. Audit dan replay juga memerlukan layer perubahan mentah yang immutable. Status akhir saja tidak dapat merekonstruksi riwayat.
- Di mana waktu latensi dua menit dimulai dan berakhir? Masalah ini mengukur dari commit sumber hingga data terkurasi yang dapat di-query. Persyaratan yang berhenti saat event mentah masuk ke broker jauh lebih mudah.
- Haruskah transaksi multi-tabel terlihat secara atomik? Default di sini adalah pengurutan per baris dengan visibilitas parsial singkat di warehouse. Konsumen finansial yang membutuhkan atomisitas seluruh transaksi memerlukan perakitan BEGIN/END.
- Apakah setiap tabel memiliki primary key yang stabil? Tanpa primary key, menemukan dan mendeduplikasi event UPDATE dan DELETE lebih sulit. Tambahkan business key atau terima secara eksplisit identitas baris penuh, surrogate key, dan biaya penyimpanan yang lebih besar.
- Apakah failover sumber mempertahankan logical replication slot? Jika tidak, pemulihan memerlukan jeda write terkontrol, verifikasi last-LSN, pembuatan ulang slot, dan rekonsiliasi. Failover primary tidak dapat diperlakukan sebagai penyambungan kembali biasa.
- Perubahan skema mana yang boleh lolos secara otomatis? Desain ini secara otomatis menerima perubahan yang kompatibel seperti penambahan kolom nullable. Drop, rename, perubahan tipe data yang menyempit, dan perubahan primary key menggunakan migrasi terkontrol.
- Mana yang lebih sulit, batas waktu snapshot 72 jam atau anggaran sumber 5%? Membaca 8 TB dalam 72 jam membutuhkan throughput efektif agregat sekitar 30,9 MB/s. Jika uji beban menunjukkan bahwa hal ini melanggar anggaran sumber, perpanjang batas waktu, gunakan replika yang valid secara semantik, atau kurangi cakupan secara bertahap.
- Berapa lama stream online harus mampu menyerap pemadaman di tujuan? Desain ini mencakup pemadaman peak selama 30 menit secara online. Stream durable tujuh hari dan arsip objek menangani replay yang lebih lama.
Jawaban 30 Detik
“Saya akan mendefinisikan correctness terlebih dahulu: snapshot dan stream tidak memiliki celah, sebuah baris konvergen berdasarkan posisi sumber, replay aman, delete terpropagasi, dan riwayat replication slot yang hilang akan fail-closed. Setiap sumber PostgreSQL menggunakan logical decoding melalui WAL, mengambil snapshot yang konsisten, dan melanjutkan dari LSN yang sesuai. Event dipartisi berdasarkan sumber, tabel, dan primary key ke dalam stream yang durable. Layer mentah tetap immutable, sementara sink terkurasi melakukan operasi MERGE yang idempoten berdasarkan primary key dan versi sumber. Kompatibilitas skema diperiksa sebelum penerapan, serta delete dan perubahan key dilakukan secara eksplisit. Saya akan memantau kesegaran tersegmentasi, lag LSN, retained WAL, progres snapshot, dan selisih rekonsiliasi, lalu menginjeksikan crash konektor, hilangnya slot, perubahan skema, dan pemadaman sink.”
Pembahasan Mendalam Langkah demi Langkah
Langkah 1: Menentukan ukuran buffer, snapshot, dan anggaran pemulihan
Beban rata-rata adalah:
20,000 events/s × 1 KB ≈ 20 MB/s
20,000 × 86,400 = 1,728,000,000 events/day
20 MB/s × 86,400 ≈ 1.728 TB/dayIngress pada saat peak adalah sekitar 60 MB/s. Jika tujuan berhenti selama 30 menit pada saat peak, backlog mentah diperkirakan sebesar:
60 MB/s × 1,800 seconds = 108 GBTujuh hari pada laju rata-rata adalah sekitar 12,096 TB data mentah sebelum replikasi, indeks, dan overhead enkoding. Tentukan ukuran broker, object store, dan jaringan untuk traffic peak dan catch-up, bukan hanya rata-rata 20 MB/s. Jika konsumen yang pulih hanya dapat menyamai laju input live, ia tidak akan pernah menghabiskan backlog 108 GB tersebut; desain membutuhkan kapasitas konsumsi cadangan atau pelonggaran sementara pada latensi layer terkurasi.
Menyelesaikan snapshot 8 TB dalam 72 jam membutuhkan setidaknya:
8 TB ÷ 72 hours ≈ 30.9 MB/sItu adalah batas bawah yang belum termasuk amplifikasi scan, serialisasi, retry jaringan, dan penulisan target. Lakukan benchmark snapshot berbasis chunk pada data berkarakteristik produksi, lalu terapkan rate-limit berdasarkan I/O sumber, perilaku cache, lag replikasi, dan p99. Jika tenggat waktu berbenturan dengan anggaran sumber 5%, ubah tenggat waktu atau jalur sumber alih-alih membebani OLTP.
Langkah 2: Buat setiap komponen menjawab kebutuhan correctness atau kapasitas
Alur data utama adalah:
PostgreSQL WAL / logical slot
→ source connector
→ durable change stream keyed by source + table + primary key
→ immutable raw archive
→ schema validation and light normalization
→ sink staging tables
→ idempotent MERGE / DELETE into curated tables
→ warehouse and lakehouse consumersBerikan setiap database sumber pengidentifikasi sumber, konektor, dan replication slot-nya sendiri agar satu domain kegagalan tidak menghentikan semua sumber. Stream durable menyerap lonjakan, memisahkan konsumen, dan mendukung replay jangka pendek. Object storage menyimpan riwayat yang lebih panjang. Batasi layer pemrosesan CDC hanya pada validasi skema, normalisasi, dan routing; lookup eksternal yang tidak dapat di-replay di jalur utama membuat pemulihan lebih sulit. Tulis ke warehouse melalui tabel staging dan batch MERGE atomik kecil untuk menyeimbangkan SLA dua menit dengan penulisan kolumnar yang efisien.
Gunakan enkoding yang stabil dari (source_id, table_id, primary_key) sebagai partition key agar perubahan untuk satu baris masuk ke satu partisi yang terurut. Ini tidak menyediakan urutan global, dan urutan global memang tidak diperlukan. Ke-20 database sumber memiliki urutan LSN terpisah yang nilai numeriknya tidak memiliki arti lintas sumber.
Langkah 3: Lakukan snapshot awal write-online
Urutan logisnya adalah:
- Buat logical replication slot sehingga WAL yang diperlukan tidak dapat direklamasi sebelum konektor mengonsumsinya.
- Dapatkan snapshot yang konsisten dan posisi log sumber yang sesuai.
- Baca snapshot dalam chunk tabel dan primary key, memancarkan baris saat ini sebagai event
READ. - Lakukan streaming data INSERT, UPDATE, dan DELETE yang di-commit dari posisi yang terkait dengan snapshot.
- Biarkan sink konvergen berdasarkan versi sumber, memungkinkan replay batas selama pemulihan tetapi tidak pernah membiarkan adanya interval yang hilang.
Konektor dapat mengimplementasikan snapshot konsisten penuh atau jendela snapshot inkremental. Jawaban tidak boleh mengarang protokol “catat LSN, lalu jalankan pernyataan SELECT biasa” karena isolasi, transaksi panjang, dan penulisan konkuren membuatnya sangat kompleks. Andalkan semantik konektor yang terverifikasi dan uji satu primary key yang diperbarui, dihapus, dan dibuat ulang berulang kali saat chunk snapshot-nya sedang berjalan.
Bagi menjadi chunk berdasarkan rentang primary key dan simpan progresnya. Chunk yang lebih kecil mengurangi transaksi panjang, gangguan cache, dan pengerjaan ulang akibat kegagalan; chunk yang terlalu kecil menambah overhead query dan penjadwalan. Terapkan rate-limit pada setiap sumber secara independen, bangun keyakinan end-to-end dengan tabel-tabel kecil terlebih dahulu, lalu proses tabel-tabel besar. Konektor harus terus menguras WAL selama snapshot berjalan atau retained WAL akan membengkak. Jika konektor yang dipilih tidak mendukung perubahan skema selama snapshot inkremental, bekukan DDL untuk tabel tersebut atau jeda snapshot-nya.
Langkah 4: Tentukan event, pengurutan, dan penerapan idempoten
Event yang dinormalisasi setidaknya mencakup:
ChangeEvent {
event_id
source_id
table_id
primary_key
operation // READ | CREATE | UPDATE | DELETE
before
after
source_lsn
transaction_id
transaction_order
source_commit_time
schema_version
captured_at
}Dalam satu sumber, source_lsn ditambah urutan transaksi menetapkan urutan event. Version key harus menyertakan source_id karena LSN dari database yang berbeda tidak berbagi sistem koordinat. Untuk setiap (source_id, table_id, primary_key), target menyimpan versi sumber terakhir yang diterapkan. Sink mengakui versi yang sama atau lebih lama tanpa mengubah baris. Versi yang lebih baru memperbarui baris bisnis dan versi yang diterapkan dalam satu transaksi target.
Ini membuat jendela kegagalan at-least-once utama dapat dikelola:
- Event mencapai stream durable tetapi offset sumbernya tidak tercatat: pemulihan memancarkannya kembali, dan sink mengabaikan versi yang sama.
- MERGE target ter-commit tetapi acknowledgement hilang: batch di-replay dan konvergen ke status yang sama.
- Konsumen crash di tengah-tengah batch: baris yang ter-commit di-replay dengan aman dan baris yang belum di-commit diproses kembali.
Jika tujuan memerlukan atomisitas transaksi multi-baris, aktifkan metadata batas transaksi dan lakukan buffer berdasarkan transaction_id hingga END, lalu commit transaksi lengkap secara bersama-sama. Transaksi besar menghabiskan lebih banyak memori dan meningkatkan tail latency, serta logika timeout atau pemulihan harus menentukan apakah transaksi telah selesai. Warehouse analitis normal yang hanya membutuhkan konsistensi eventual tingkat baris sebaiknya tidak menerima kompleksitas ini tanpa kebutuhan nyata.
Langkah 5: Tangani delete, perubahan key, dan evolusi skema dengan benar
Event DELETE harus membawa informasi key yang cukup bagi layer terkurasi untuk melakukan hard-delete pada baris, menyetel is_deleted, atau mempertahankan riwayat. Tombstone yang mengikuti operasi delete terutama mendukung pemadatan log. Tombstone tidak dapat menggantikan event delete bisnis, dan middleware tidak boleh membuang delete sebelum mencapai target.
Ketika nilai primary key berubah, semantik CDC umum memancarkan delete untuk key lama dan create untuk key baru. Sink harus menerapkan keduanya atau key lama akan tetap ada sebagai ghost row. Mengubah definisi primary key lebih berisiko daripada mengubah nilai. Gunakan jendela read-only atau jeda penulisan, kuras konektor, perbarui skema, lalu lanjutkan karena bentuk event key dapat menjadi tidak konsisten selama transisi.
Gunakan kebijakan kompatibilitas yang eksplisit:
- Penambahan kolom nullable: daftarkan versi baru, biarkan konsumen lama mengabaikan field yang tidak dikenal, perluas tabel terkurasi sebelum mengaktifkan penulisan.
- Kolom yang di-drop atau di-rename: perkenalkan dan isi field baru, migrasikan setiap konsumen, lalu hapus field lama.
- Tipe data diperlebar: upgrade setelah pemeriksaan kompatibilitas target. Tipe yang dipersempit atau perubahan semantik mengarantina event yang tidak kompatibel.
- Perubahan primary key: tangani sebagai migrasi terpisah alih-alih evolusi otomatis diam-diam.
Event yang tidak kompatibel masuk ke karantina dan memicu peringatan. Offset utama dapat maju hanya setelah event disimpan secara durable, dapat di-replay, dan memiliki penanggung jawab remediasi yang jelas. Melewatkan skema yang buruk secara diam-diam akan menciptakan celah data yang tidak terlihat.
Langkah 6: Perlakukan pemulihan, replay, dan rekonsiliasi sebagai jalur normal
Pemulihan konektor memerlukan offset yang persisten dan replication slot yang masih berisi riwayat terkait. Pantau restart_lsn, confirmed_flush_lsn, posisi WAL saat ini, byte yang ditahan, laju pertumbuhan, dan waktu hingga disk habis. Pemadaman di tujuan seharusnya terakumulasi di dalam stream durable alih-alih menghentikan acknowledgement konektor cukup lama hingga menahan WAL tanpa batas di sumber.
Jika slot hilang, offset yang tersimpan berada di belakang posisi slot yang tersedia, atau WAL yang diperlukan sudah hilang, lakukan fail-closed. Hentikan publikasi data terkurasi untuk sumber tersebut, catat posisi tepercaya terakhir, buat snapshot ulang untuk tabel yang terpengaruh, dan lakukan rekonsiliasi berdasarkan rentang. Slot yang baru dibuat hanya menangkap perubahan setelah pembuatannya dan tidak dapat membuktikan bahwa interval sebelumnya lengkap.
Replay memiliki replay_job_id-nya sendiri, cakupan tabel dan primary key, serta batas waktu sumber. Replay membaca layer mentah yang immutable ke staging. Data live dan replay menggunakan aturan MERGE versi sumber yang sama sehingga backfill yang lebih lama tidak dapat menimpa status yang lebih baru. Ketika logika transformasi berubah, buat versi terkurasi baru atau shadow table terlebih dahulu; membandingkan dan melakukan rollback lebih aman daripada langsung menimpa produksi.
Rekonsiliasi mencakup setidaknya empat layer:
- Kontinuitas dari posisi commit sumber ke konektor, stream durable, dan posisi target yang diterapkan.
- Jumlah baris, jumlah delete, dan checksum berdasarkan tabel, tanggal, dan bucket primary key.
- Perbandingan primary key tersampel antara status sumber saat ini dan status tujuan terbaru.
- Transaksi canary berkala yang dapat diidentifikasi untuk memverifikasi visibilitas INSERT, UPDATE, dan DELETE dalam SLA.
Bagi latensi end-to-end menjadi commit sumber ke penangkapan, penangkapan ke stream, stream ke staging, dan staging ke terkurasi. Pantau juga laju event per sumber, lag LSN, retained WAL pada slot, progres chunk snapshot, versi duplikat atau usang, karantina skema, kegagalan MERGE target, delta rekonsiliasi, dan estimasi waktu catch-up.
Langkah 7: Jelaskan batasan dari pendekatan alternatif
Polling berdasarkan updated_at sederhana untuk tabel dengan frekuensi penulisan rendah dengan kesegaran tingkat menit dan rescan yang dapat diterima. Pendekatan ini menambah beban query, mudah melewatkan hard delete, dan tetap harus menangani timestamp yang sama serta presisi jam. Trigger dapat menulis delete ke dalam tabel audit, tetapi menambah beban kerja dan kopling operasional ke jalur penulisan sumber. CDC berbasis log adalah pilihan default yang lebih baik untuk beban kerja OLTP yang sibuk dalam masalah ini.
Pola outbox memecahkan masalah yang berbeda: layanan menulis status bisnis dan domain event dalam satu transaksi database, menghindari skenario commit database berhasil yang diikuti oleh kegagalan pengiriman pesan. Pola ini tepat untuk event bisnis terpilih. Pola ini tidak otomatis menggantikan sinkronisasi tingkat baris generik untuk 200 tabel. Keduanya dapat hidup berdampingan: integrasi layanan mengonsumsi outbox, sementara analitik dan audit mengonsumsi CDC.
Contoh Jawaban yang Kuat
“Saya akan mulai dengan jaminan-jaminannya. Setiap perubahan ter-commit yang masih ada di WAL atau stream durable harus dapat dipulihkan. Sebuah baris konvergen berdasarkan posisi sumber, replay tidak mengubah status akhirnya, dan delete sampai ke target. Jika replication slot dan posisi historis tidak lagi utuh, publikasi berhenti dan data yang terpengaruh di-snapshot ulang; konektor tidak boleh memulai ulang secara diam-diam pada posisi terbaru.
Pada beban rata-rata, ingress sekitar 20 MB/s, 1,728 miliar event dan 1,728 TB per hari. Peak adalah 60 MB/s, sehingga pemadaman target selama 30 menit menciptakan backlog sekitar 108 GB. Retensi mentah tujuh hari sekitar 12,096 TB. Snapshot 8 TB membutuhkan pembacaan efektif setidaknya 30,9 MB/s agar selesai dalam 72 jam, jadi saya akan melakukan benchmark dan membatasi laju setiap sumber berdasarkan p99, I/O, dan retained WAL.
Setiap sumber PostgreSQL mendapatkan logical slot dan konektor independen. Konektor mengambil snapshot yang konsisten dan kemudian melanjutkan perubahan yang di-commit dari LSN yang sesuai. Event dipartisi berdasarkan sumber, tabel, dan primary key ke dalam stream durable dan disalin ke layer mentah yang immutable. Pemrosesan ringan memvalidasi skema dan menormalisasi envelope. Warehouse memuat tabel staging, lalu melakukan operasi MERGE atau DELETE yang idempoten berdasarkan primary key dan versi sumber. LSN tidak pernah dibandingkan lintas database; urutan transaksi melengkapi LSN di dalam satu transaksi.
Snapshot dibagi menjadi chunk berdasarkan rentang primary key, progres disimpan secara persisten, dan beban sumber dibatasi secara dinamis. WAL dikuras saat snapshot berjalan, dan aturan versi sumber pada target menyerap replay pemulihan pada batas tersebut. Event berisi operasi, nilai before dan after, LSN sumber, identitas serta urutan transaksi, dan versi skema. Sink hanya menerapkan versi yang lebih baru, sehingga replay konektor, acknowledgement target yang hilang, dan crash konsumen semuanya konvergen dengan aman.
Event delete tetap utuh melalui layer terkurasi; tombstone hanya untuk pemadatan. Perubahan nilai primary key diterapkan sebagai delete key lama ditambah create key baru. Penambahan kolom nullable dapat berevolusi secara kompatibel, sedangkan drop, rename, penyempitan tipe data, dan perubahan key menggunakan migrasi terkontrol. Data yang tidak kompatibel dikarantina dan dapat di-replay alih-alih dilewati secara diam-diam.
Secara operasional, saya akan memantau latensi tersegmentasi, lag LSN per sumber, retained WAL pada slot dan headroom disk, progres snapshot, karantina skema, kegagalan target, dan delta rekonsiliasi. Hilangnya slot akan fail-closed dan memicu pembuatan snapshot ulang pada cakupan yang terpengaruh. Terakhir, saya akan menginjeksikan penulisan konkuren selama snapshot, pengiriman duplikat, delete, perubahan key, crash konektor, hilangnya acknowledgement sink, pemadaman sink 30 menit, hilangnya slot, dan perubahan skema yang merusak (breaking). Jumlah baris, checksum bucket key, sampel baris, dan transaksi canary akan membuktikan bahwa tidak ada perubahan yang hilang dan tidak ada event usang yang menimpa status yang lebih baru.”
Kesalahan Umum
- Mengekspor setiap tabel dan baru mengaktifkan CDC setelahnya → WAL dari interval ekspor dapat hilang, meninggalkan celah antara snapshot dan stream → Tetapkan retensi log dan posisi snapshot yang konsisten sebelum melakukan streaming dari titik yang sesuai.
- Hanya mengatakan “gunakan Debezium dan Kafka” → Nama produk tidak mendefinisikan latensi, pengurutan, pemulihan, atau idempotensi sink → Nyatakan invarian correctness dan kapasitas terlebih dahulu, lalu petakan setiap komponen ke dalamnya.
- Membandingkan LSN dari database yang berbeda sebagai satu versi global → Setiap sumber memiliki koordinat log independen → Sertakan
source_iddalam versi dan bandingkan posisi hanya di dalam urutan satu sumber. - Mengasumsikan exactly-once pada broker membuat warehouse menjadi exactly-once → MERGE eksternal dapat berada di luar transaksi broker dan melakukan replay setelah acknowledgement hilang → Terapkan perubahan secara idempoten berdasarkan primary key dan versi sumber.
- Menunggu tanpa batas waktu untuk konektor yang macet → Slot-nya dapat menahan WAL hingga penyimpanan sumber penuh → Pantau byte yang ditahan dan waktu hingga disk habis, isolasi pemadaman sink dengan stream durable, dan tetapkan ambang batas stop-loss.
- Membuat ulang slot yang hilang dan melanjutkan pada posisi terbaru → Slot baru tidak memiliki riwayat sebelumnya dan dapat menyembunyikan data yang hilang → Fail-closed, buat snapshot ulang, dan rekonsiliasi cakupan yang terpengaruh.
- Memperlakukan tombstone sebagai satu-satunya sinyal delete → Penanda pemadatan tidak dapat menggantikan DELETE bisnis yang membawa key baris → Pertahankan event delete dan pilih hard delete, soft delete, atau riwayat di tujuan.
- Menerima setiap perubahan skema secara otomatis → Drop, penyempitan tipe data, dan perubahan key dapat merusak konsumen atau event key → Definisikan matriks kompatibilitas, karantina data yang tidak kompatibel, dan lakukan tahapan migrasi yang merusak.
- Hanya mengoptimalkan untuk tenggat waktu snapshot 72 jam → Scan besar dapat merusak p99 sumber, perilaku cache, dan replikasi → Lakukan benchmark batas bawah 30,9 MB/s, terapkan rate-limit dinamis, dan lindungi anggaran sumber.
- Hanya membandingkan jumlah total baris → Update yang salah diterapkan, delete yang terlewat, dan kesalahan yang saling meniadakan dapat tetap tersembunyi → Bandingkan jumlah dan checksum berdasarkan bucket key, ambil sampel baris, dan injeksikan canary.
Pertanyaan Lanjutan
Pertanyaan lanjutan 1: Bagaimana Anda membuktikan bahwa update dan delete selama snapshot tidak dapat membuat nilai snapshot lama menimpa status baru?
Gunakan semantik consistent-snapshot dan log-handoff yang terverifikasi dari konektor alih-alih menebak-nebak waktu aplikasi. Sink menyimpan versi sumber per baris dan hanya menerima versi yang lebih baru, sehingga READ yang di-replay tidak dapat menimpa UPDATE atau DELETE yang lebih baru. Dalam pengujian, perbarui, hapus, dan buat ulang satu key berulang kali di sekitar chunk snapshot-nya, lalu pastikan kesetaraan akhir sumber-ke-target dan kontinuitas posisi sumber.
Pertanyaan lanjutan 2: Bagaimana Anda memperkirakan waktu pemulihan setelah pemadaman warehouse selama 30 menit?
Backlog saat peak adalah sekitar 108 GB. Waktu pemulihan tergantung pada throughput yang pulih dikurangi ingress live yang terus berjalan. Jika traffic live kembali ke rata-rata 20 MB/s dan konsumen mempertahankan 80 MB/s, net laju catch-up adalah sekitar 60 MB/s, membuat waktu pengurasan teoretis sekitar 30 menit sebelum amplifikasi MERGE dan margin keamanan. Jika pemrosesan hanya sama dengan ingress live, backlog tidak akan pernah berkurang.
Pertanyaan lanjutan 3: Apa yang berubah jika semua baris dalam satu transaksi sumber harus terlihat secara bersamaan?
Aktifkan metadata batas transaksi, rakit event berdasarkan ID transaksi, dan commit transaksi ke staging dan publikasi hanya setelah batas END lengkap tercapai. Simpan transaksi besar ke disk secara persisten, definisikan jalur timeout dan remediasi, dan lanjutkan dari status perakitan yang durable. Ini meningkatkan tail latency dan biaya state, jadi pastikan terlebih dahulu bahwa inkonsistensi lintas tabel yang singkat memang benar-benar tidak dapat diterima oleh konsumen.
Pertanyaan lanjutan 4: Jika replication slot hilang tetapi stream durable masih memiliki data 7 hari, apakah Anda harus menjalankan snapshot penuh?
Cari potensi celahnya terlebih dahulu. Jika stream durable terbukti berisi setiap perubahan setelah LSN tepercaya terakhir, replay dan rekonsiliasi dapat memulihkan kontinuitas tanpa snapshot penuh. Jika slot menghilang sebelum event mencapai stream, atau batas celah tidak dapat dibuktikan, lakukan snapshot ulang pada tabel atau rentang primary key yang terpengaruh. Keputusan mengikuti kontinuitas yang dapat dibuktikan, bukan biaya pengerjaan ulang.
Pertanyaan lanjutan 5: Mengapa tidak mengganti seluruh desain dengan outbox?
Outbox sangat baik ketika sebuah layanan secara eksplisit memublikasikan domain event seperti order-created atau payment-completed dan menulis event tersebut dalam transaksi yang sama dengan status bisnis. Pendekatan ini membutuhkan partisipasi aplikasi dan hanya berisi fakta-fakta terpilih. Masalah ini menyinkronkan insert, update, dan delete di 200 tabel untuk analitik, sehingga CDC tingkat baris yang generik tetap diperlukan. Kedua pola ini dapat hidup berdampingan untuk konsumen yang berbeda.