1. Pertanyaan
Sebuah stream event pesanan di-parse, dikelompokkan dalam jendela waktu (windowed), diagregasi, dan dinilai risikonya. Hasilnya ditulis ke warehouse dan notifikasi downstream dipicu. Worker dapat mengalami crash, jaringan dapat mengalami timeout, dan event dapat datang terlambat. Jelaskan batasan exactly-once dan rancang alur yang tidak menimbulkan tagihan ganda selama proses percobaan ulang (retry).
2. Batasan dan klarifikasi
- Pisahkan tiga lapisan: pengiriman pesan, hasil di dalam pipeline, dan efek samping eksternal.
- Event mungkin terduplikasi, tidak berurutan, atau terlambat; log pemrosesan bukanlah bukti dari hasil yang telah di-commit.
- Hasil harus dapat diputar ulang, sedangkan notifikasi dan panggilan eksternal lainnya memerlukan idempoten atau deduplikasi.
- Perjelas latensi, jendela keterlambatan (lateness windows), dan kebijakan pembuangan (dropping policy) sebelum memilih implementasi.
3. Konsep inti
Pemrosesan exactly-once biasanya berarti hasil pipeline suatu data tercermin paling banyak satu kali dalam output yang tahan lama (durable) sementara sistem tetap mencegah hilangnya data tersebut. Ini tidak berarti setiap fungsi pengguna hanya berjalan sekali, dan ini tidak secara otomatis mencakup panggilan HTTP, email, atau database. Input at-least-once ditambah checkpoint, pemutaran ulang deterministik, dan deduplikasi hasil dapat menghasilkan jaminan output yang dapat diverifikasi.
4. Alur referensi
onEvent(event):
key = stableEventId(event)
state = readCheckpointOrState(key)
result = deterministicTransform(event, state)
writeTransactionalResult(key, result) # unique(key)
commitCheckpointAfterResult(key)
onExternalSideEffect(result):
idempotencyKey = result.eventId + ":" + result.version
callOrOutbox(idempotencyKey, result.payload)Pertama, tulis hasil dan ID event ke penyimpanan dengan batasan keunikan (uniqueness constraint) atau transaksi, lalu majukan checkpoint. Rute notifikasi eksternal melalui API yang idempoten atau pola outbox dan pengirim terpisah. Pengirim dapat mencoba ulang, sedangkan penerima hanya menerima kunci idempoten tertentu satu kali.
5. Kasus kegagalan dan trade-off
Jika worker mengalami crash setelah panggilan eksternal berhasil tetapi sebelum checkpoint-nya di-commit, pemutaran ulang akan memanggil layanan eksternal lagi. Tanpa kunci idempoten, runner saja tidak dapat menghilangkan efek samping duplikat tersebut. Hasil window juga bergantung pada data yang terlambat dan watermark, sehingga batas koreksi harus eksplisit. Jaminan end-to-end yang lebih kuat menambah status deduplikasi, koordinasi transaksi, dan biaya penyimpanan; jika duplikat dapat diterima, at-least-once dapat memberikan latensi yang lebih rendah.
6. Verifikasi dan observabilitas
- Injeksikan crash, timeout, pesan duplikat, dan event yang tidak berurutan; periksa hasil akhir untuk satu kunci bisnis.
- Catat ID event input, jumlah percobaan, versi commit, temuan deduplikasi (deduplication hits), dan hasil panggilan eksternal.
- Rekonsiliasikan empat hitungan: diterima, diproses, di-commit, dan dinotifikasikan. Log worker saja tidak cukup.
- Pantau tingkat duplikasi, keterlambatan, usia checkpoint, ukuran status deduplikasi, dan backlog pemutaran ulang.
7. Kesalahan umum
- Memperlakukan pengiriman exactly-once, pemrosesan exactly-once, dan efek samping exactly-once sebagai satu janji yang sama.
- Mengasumsikan opsi konfigurasi framework memberikan efek satu kali pada kode kustom sembarang dan API eksternal.
- Melakukan deduplikasi dengan timestamp alih-alih ID event yang stabil, sehingga menghasilkan kunci yang berbeda saat percobaan ulang atau pemutaran ulang.
- Mengabaikan event yang terlambat, konflik versi, dan retensi catatan deduplikasi.
8. Poin penilaian wawancara
Menentukan batas jaminan
Kandidat memisahkan pengiriman, hasil pipeline, dan efek samping eksternal, serta mengidentifikasi lapisan mana yang sebenarnya dicakup oleh framework.
Merancang alur yang dapat diputar ulang
Kandidat menggunakan ID event yang stabil, transformasi deterministik, commit hasil transaksional, dan urutan checkpoint, lalu menjelaskan pemulihan saat crash.
Menangani efek samping eksternal
Kandidat mengusulkan kunci idempoten, batasan keunikan, atau outbox serta menjelaskan bagaimana pengirim dan penerima bersama-sama mencegah duplikat.
Memverifikasi dengan injeksi kesalahan
Kandidat mencakup duplikat, perubahan urutan, keterlambatan, timeout, dan crash pada worker, menggunakan data yang di-commit dan rekonsiliasi bisnis untuk memvalidasi klaim tersebut.