Konteks dan cakupan
Ini adalah pertanyaan desain yang umum untuk posisi data-platform, analitik real-time, dan senior data-engineering. Asumsikan puncak 50.000 event per detik, target kesegaran (freshness) dasbor 60 detik, dan laporan untuk hari sebelumnya yang harus selesai pada pukul 07:00. Wawancara ini menguji kapan execution graph bersama memaksa setiap konsumen mewarisi SLO yang paling ketat, dan bagaimana progres independen serta kumpulan sumber daya mengurangi kopling (coupling).
Hal yang dinilai pewawancara
- Apakah Anda mengubah "real time" dan "tepat waktu" menjadi SLO end-to-end sebelum menyebutkan nama tools.
- Apakah Anda membedakan antara cabang di dalam satu graf Beam, langganan independen ke satu sumber, dan sumber daya komputasi yang sepenuhnya independen.
- Apakah Anda dapat menjelaskan kompromi (trade-offs) antara pembacaan duplikat, biaya, backpressure, replay, event yang terlambat, dan domain kegagalan.
- Apakah Anda menyediakan metrik, canary, rollback, dan rekonsiliasi yang membuktikan bahwa pemisahan tersebut meningkatkan hasil bagi pengguna.
Pertanyaan klarifikasi yang perlu diajukan terlebih dahulu
Tanyakan apakah 60 detik berarti kesegaran dari waktu event hingga dapat di-query (event-time-to-queryable freshness) atau hanya latensi pemroses; apakah laporan keuangan boleh melakukan backfill pada partisi yang terlambat; apakah kedua konsumen dapat berbagi penyimpanan mentah yang immutable; apakah event memerlukan keadilan untuk tenant atau prioritas; jaminan duplikasi, kehilangan, dan pengurutan apa yang diperlukan; dan apakah anggaran lebih memprioritaskan biaya atau latensi ekor (tail latency) dasbor. Jika laporan adalah T+1 tetapi dasbor memiliki target latensi rendah yang ketat, isolasi sudah menjadi pilihan default yang masuk akal untuk dievaluasi.
Struktur jawaban 30 detik
Saya akan mencatat SLO end-to-end dari kedua konsumen, jaminan kebenaran (correctness), dan target pemulihan. Jika satu shared pipeline harus memenuhi target 60 detik yang ketat, saya akan menetapkan baseline bersama, lalu menggunakan langganan independen untuk memisahkan progres real-time dan batch. Saya akan berbagi proses parsing umum yang berat, tetapi memisahkan komputasi ketika tekanan sumber daya atau perambatan kegagalan menjadi signifikan. Setiap jalur mendapatkan metrik kesegaran, backlog, kelambatan, duplikat, dan penyelesaian laporannya sendiri, serta replay dan injeksi kegagalan menentukan apakah isolasi tambahan tersebut sebanding dengan biayanya.
Jawaban mendalam
1. Menurunkan struktur dari SLO
Definisikan SLO real-time sebagai p99 kesegaran waktu-event-hingga-dapat-di-query di bawah 60 detik. Definisikan SLO batch sebagai penyelesaian event hari sebelumnya yang valid sebelum pukul 07:00, dengan data yang terlambat masuk ke jendela perbaikan (repair window) yang terbatas. Panduan Dataflow dari Google mencatat bahwa satu pipeline tunggal yang melayani SLO campuran harus memenuhi target yang lebih ketat, yang memungkinkan pekerjaan berprioritas lebih rendah menghabiskan kapasitas real-time. Perbedaan error budget, rute peringatan, atau kebijakan autoscaling adalah alasan kuat untuk memisahkan jalur.
2. Membandingkan tiga topologi
Cabang in-graph berguna untuk decoding bersama dan routing yang ringan. Dokumentasi Apache Beam menyebutkan bahwa beberapa transformasi dapat membaca PCollection yang sama, tetapi setiap transformasi memproses input tersebut lagi; satu transformasi multi-output dapat memproses setiap elemen sekali untuk pekerjaan bersama.
Langganan independen ke satu topik memungkinkan konsumen real-time dan batch memiliki acknowledgement, backlog, dan posisi replay yang terpisah. Panduan Dataflow dari Google menjelaskan beberapa pipeline yang menggunakan langganan terpisah sehingga setiap pekerjaan menarik dan mengonfirmasi (ack) secara independen. Pekerjaan yang sepenuhnya independen juga mengisolasi CPU, memori, irama rilis, dan domain kegagalan, dengan konsekuensi biaya pembacaan duplikat, serialisasi, dan kepemilikan operasional.
3. Merancang jalur yang direkomendasikan
Pertahankan satu lapisan raw-event yang immutable dan buat langganan real-time ditambah langganan batch dari sumber yang sama. Pekerjaan real-time melakukan agregasi ringan ke dalam storage penyajian berlatensi rendah. Pekerjaan batch membaca data yang disimpan berdasarkan tanggal event dan menulis tabel yang dipartisi. Jika parsing umum memakan lebih dari 20% dari total CPU, lakukan normalisasi sekali pada saat masuk (ingress) dan tulis event berversi ke lapisan mentah; jangan menganggap progres konsumen real-time sebagai bukti bahwa jalur batch telah di-commit.
raw-events
-> realtime-subscription -> stream-aggregate -> serving-store
-> batch-subscription or retained-raw -> daily-transform -> partitioned-lake4. Menangani backpressure, prioritas, dan biaya
Berikan jalur real-time batas konkurensi dan peringatan backlog-nya sendiri. Biarkan batch mengurangi konkurensi saat sumber daya real-time menipis, tetapi jangan letakkan keduanya di belakang satu antrean tanpa batas. Jika dua komputasi lengkap terlalu mahal, gunakan decoding dan pendaratan mentah bersama, lalu isolasi tahap downstream. Saat backlog real-time melebihi 60 detik, hentikan perluasan kapasitas batch dan pulihkan SLO real-time terlebih dahulu. Atribusikan byte input, CPU, usia backlog, dan biaya per juta event ke masing-masing jalur daripada membandingkan jumlah pekerjaan.
5. Menangani keterlambatan, replay, dan pemulihan
Gunakan watermark dan allowed lateness yang dibatasi untuk jendela real-time. Rute event di luar jendela tersebut ke antrean late-data atau lapisan mentah, lalu biarkan batch memperbaiki partisi yang terpengaruh dengan penulisan yang berversi dan idempoten. Lakukan pemutaran ulang (replay) dari posisi sumber yang disimpan dengan membuat langganan baru; jangan pernah memundurkan posisi acknowledgement milik konsumen produksi. Jalur batch harus tetap dapat pulih dari data mentah setelah terjadi kegagalan real-time. Jika penyimpanan mentah tidak tersedia, kedua jalur memerlukan degradasi eksplisit dan peringatan.
6. Gunakan eksperimen penerimaan untuk memutuskan
Jalankan baseline bersama terlebih dahulu, lalu aktifkan sumber daya terisolasi untuk sebagian kecil tenant. Bandingkan kesegaran p50/p95/p99 dasbor, penyelesaian laporan, usia backlog, tingkat duplikasi, waktu replay, CPU, penyimpanan, dan biaya per juta event. Injeksikan lonjakan (burst) batch, restart pemroses, pesan duplikat, partisi terlambat, dan langganan yang dijeda. Jika pemisahan hanya meningkatkan latensi pemroses tetapi meningkatkan data duplikat atau melebihi anggaran biaya, pertahankan rencana bersama dan optimalkan tahap umumnya.
Contoh jawaban yang kuat
Saya akan mendefinisikan dua SLO end-to-end terlebih dahulu: kesegaran p99 waktu-event-hingga-dapat-di-query dasbor di bawah 60 detik, dan laporan keuangan hari sebelumnya yang selesai sebelum pukul 07:00 dengan jendela perbaikan late-data yang terbatas. Saya akan membangun baseline bersama tetapi tidak akan pernah berbagi posisi acknowledgement antara real-time dan batch. Desain default saya adalah satu lapisan raw-event yang immutable, dua langganan independen, dan dua downstream jobs. Pekerjaan real-time melakukan agregasi ringan; pekerjaan batch membaca data yang disimpan berdasarkan tanggal event. Parsing umum dapat dibuat berversi sekali pada ingress, sementara pemisahan pekerjaan penuh hanya dilakukan jika sumber daya atau domain kegagalan memerlukannya. Setiap jalur memiliki metrik kesegaran, backlog, keterlambatan, duplikat, penyelesaian laporan, dan biaya per unit; replay menggunakan langganan baru dan kunci idempotensi. Saya akan menginjeksikan burst, restart, dan event terlambat untuk memverifikasi SLO. Jika isolasi tidak meningkatkan hasil bagi pengguna, saya akan mempertahankan komputasi bersama dan mengoptimalkan tahap umumnya.
Kesalahan umum
- Gejala: Menyalin dua pipeline lengkap hanya karena ada dua konsumen. Penyebab kegagalan: Biaya parsing umum dan penampungan data berlipat ganda tanpa meningkatkan isolasi. Koreksi: Bagikan data mentah immutable terlebih dahulu, lalu isolasi komputasi downstream berdasarkan SLO.
- Gejala: Menjalankan kedua konsumen dengan satu offset global. Penyebab kegagalan: Konsumen yang lambat memblokir yang cepat dan replay tidak dapat dilakukan secara independen. Koreksi: Gunakan langganan independen atau progres yang dapat diverifikasi secara independen.
- Gejala: Hanya mengukur latensi pemroses. Penyebab kegagalan: Waktu penyimpanan, query, dan refresh masih dapat melanggar target pengguna. Koreksi: Ukur kesegaran end-to-end dan persentilnya.
- Gejala: Menulis event yang terlambat langsung ke hasil langsung (live result). Penyebab kegagalan: Jumlah data dapat terduplikasi atau laporan yang sudah dipublikasikan dapat berubah tanpa disadari. Koreksi: Gunakan watermark, jendela perbaikan, versi, dan kunci idempotensi.
- Gejala: Memundurkan konsumen produksi untuk melakukan replay riwayat. Penyebab kegagalan: Progres online terganggu dan lalu lintas dapat teramplifikasi. Koreksi: Buat langganan replay dengan pembatasan laju (rate-limited) dari data yang disimpan.
Pertanyaan lanjutan
Bagaimana jika kedua jalur memerlukan komputasi fitur yang sama-sama mahal?
Jadikan tahap komputasi fitur tersebut berversi dan dapat di-replay, tampung hasilnya sekali, dan biarkan kedua jalur membacanya. Terima komputasi duplikat hanya jika state harus tetap online dan tidak dapat dibagikan. Bandingkan lapisan perantara bersama dengan komputasi duplikat menggunakan eksperimen CPU, latensi, dan konsistensi.
Apakah langganan independen akan melipatgandakan biaya input?
Hal itu menambah overhead pembacaan dan konfirmasi (acknowledgement), tetapi pendaratan data yang immutable, kompresi, jendela retensi, dan replay sesuai permintaan dapat mengendalikannya. Evaluasi biaya per juta event bersama dengan SLO real-time dan isolasi kegagalan; biaya penyimpanan saja tidak cukup lengkap.
Bisakah batch meminjam kapasitas real-time ketika tertinggal?
Gunakan kapasitas berprioritas rendah yang terbatas, preemptible, dengan lease dan reklamasi otomatis. Real-time mempertahankan batas atas yang ketat dan metrik backlog independen, sehingga kapasitas yang dipinjam tidak dapat mendorong p99-nya melebihi 60 detik.
Bagaimana Anda membuktikan bahwa kedua jalur tersebut pada akhirnya selaras?
Bangun kumpulan rekonsiliasi dari versi event, business key, dan batasan waktu yang sama. Bandingkan jumlah, nilai nominal, data yang hilang, duplikat, dan koreksi yang terlambat. Jika output real-time berupa perkiraan, tentukan jendela konvergensi dan toleransi perbedaan yang dapat dijelaskan daripada memperlakukan satu total yang sama sebagai bukti mutlak.