Masalah dan cakupan
Notifikasi pesanan, transformasi gambar, dan kalkulasi tagihan sering kali merupakan item pekerjaan yang independen. Tim sudah menulis event ke Kafka, tetapi Consumer Group tradisional menetapkan satu partisi hanya ke satu anggota pada satu waktu; menambahkan lebih banyak worker melebihi jumlah partisi tidak secara langsung meningkatkan paralelisme. Rancang cara agar beberapa konsumen dapat bekerja sama dalam memproses pekerjaan, dengan acknowledgement per record, percobaan ulang, dan upaya pengiriman yang dapat diobservasi, sembari mengidentifikasi alur bisnis yang masih memerlukan pengurutan tingkat partisi.
Pertanyaan ini menggunakan model Share Group yang dijelaskan oleh Apache Kafka KIP-932. KIP tersebut menjelaskan jenis grup baru untuk konsumsi kooperatif pada topik reguler; ini tidak membuat Kafka identik dengan RabbitMQ. Jawaban yang kuat memverifikasi versi broker yang di-deploy, dukungan klien, dan ketersediaan API sebelum merekomendasikan penggunaannya di produksi.
Hal yang diuji oleh pewawancara
- Bisakah Anda membedakan penetapan partisi eksklusif dengan akuisisi record secara kooperatif?
- Bisakah Anda memetakan acknowledge, release, reject, dan habisnya masa berlaku lock (lock expiry) ke status pemrosesan?
- Tahukah Anda bahwa Share Group dapat memiliki konsumen lebih banyak daripada partisi tanpa mempertahankan intuisi urutan key seperti biasanya?
- Apakah retry, poison record, batas waktu pemrosesan, dan batas konkurensi sesuai dengan satu model kegagalan dalam jawaban Anda?
- Apakah Anda memverifikasi detail klien, broker, ACL, pemantauan, dan rollback daripada hanya menyebutkan sebuah KIP?
Jawaban yang lemah mengatakan “Kafka juga bisa menjadi antrean.” Jawaban yang kuat menyebutkan manfaat serupa antrean, jaminan yang berubah, dan kriteria (gates) yang diperlukan sebelum peluncuran.
Pertanyaan klarifikasi untuk diajukan terlebih dahulu
- Apakah pekerjaan benar-benar independen? Jika event untuk satu pesanan harus diterapkan dalam urutan key, Share Group mungkin merupakan primitif yang salah.
- Apakah kegagalan bersifat sementara, dapat dipulihkan secara manual, atau tidak valid secara permanen? Hal tersebut menentukan perilaku release, reject, dan karantina.
- Berapa waktu pemrosesan p99, konkurensi maksimum, dan efek samping duplikat yang ditoleransi? Hal-hal ini membentuk desain lock akuisisi dan idempotensi.
- Apakah bisnis memerlukan transaksi Kafka secara end-to-end? Jangan berasumsi bahwa Share Group mewarisi rencana transaksi Consumer Group yang sudah ada.
- Apakah topik tersebut masih melayani konsumen broadcast atau replay? Mengubah satu grup tidak boleh mengubah kontrak baca grup lainnya.
Jawaban 30 detik
“Pertama-tama saya akan mengonfirmasi apakah pekerjaan boleh selesai di luar urutan dan apakah Kafka serta klien yang di-deploy mendukung KIP-932. Share Group memungkinkan anggota memperoleh record dari topik secara kooperatif, memungkinkan jumlah anggota melebihi jumlah partisi, serta mendukung acknowledgement, release, dan reject per record. Consumer Group tetap lebih cocok untuk pengurutan lokal partisi dan penalaran berbasis offset. Saya akan membuat setiap efek samping bersifat idempoten, menetapkan kebijakan lock dan retry berdasarkan latensi pemrosesan, memantau status acquire, acknowledge, release, reject, dan timeout, serta mengarantina poison record. Jika pengurutan, batas transaksi, atau dukungan klien belum terselesaikan, saya akan mempertahankan Consumer Group dan memvalidasi topik kerja terpisah dengan kelompok kecil sebelum migrasi.”
Penalaran langkah demi langkah
1. Gambarkan kedua model penetapan
Consumer Group biasanya menetapkan partisi ke anggota; satu anggota membaca partisi tertentu dalam grup tersebut, sehingga paralelisme dibatasi oleh jumlah partisi. Share Group memungkinkan anggota memperoleh record secara kooperatif dari topik yang dilanggan. Beberapa anggota dapat memproses record yang berbeda dari satu partisi, dan jumlah anggota dapat melebihi jumlah partisi. Ini berguna untuk pekerjaan independen, tetapi tidak menjamin pengurutan global.
Consumer Group: partition-0 -> worker-A
partition-1 -> worker-B
extra workers wait for another partition
Share Group: partition-0 records -> worker-A, worker-B, worker-C
each acquired record is locked for one consumerAlasan memilih Share Group harus didasarkan pada akuisisi kerja yang elastis dan penyelesaian per record, bukan sekadar “partisinya terlalu sedikit.” Jika event untuk satu pelanggan harus diterapkan secara berurutan, pertahankan Consumer Group atau tambahkan state machine yang diserialisasi pada tingkat aplikasi.
2. Modelkan siklus hidup record
KIP-932 menjelaskan batas waktu lock akuisisi. Setelah memperoleh record, konsumen dapat mengonfirmasi keberhasilan (acknowledge), melepaskannya untuk pengiriman lain (release), menolaknya karena tidak dapat diproses (reject), atau tidak melakukan apa pun hingga lock kedaluwarsa. KIP menjelaskan default 30 detik, tetapi perilaku produksi harus menggunakan pengaturan broker yang di-deploy; nilai default bukanlah SLA.
available -> acquired -> acknowledged
-> released -> available
-> rejected -> terminal or quarantine
-> lock timeout -> availableHandler harus mendaftarkan key idempotensi sebelum melakukan efek samping eksternal. Jika tidak, crash pada klien atau lock yang kedaluwarsa dapat menyebabkan penagihan, pengiriman, atau notifikasi ganda. Acknowledgement menyatakan bahwa akuisisi ini telah selesai; acknowledgement tidak dapat membatalkan (rollback) efek samping yang sudah di-commit oleh sistem lain.
3. Batasi percobaan ulang (retry), poison record, dan konkurensi
Jumlah upaya pengiriman membantu memisahkan kegagalan sementara dari record yang tidak valid secara permanen. Lakukan backoff dan release untuk kegagalan jaringan. Lakukan reject untuk kesalahan skema deterministik atau validasi ke topik karantina atau antrean manual. Jangan melakukan release tanpa henti: satu poison record dapat menghabiskan lock dan kapasitas downstream tanpa batas.
Tetapkan durasi lock di atas waktu pemrosesan p99 normal dengan margin jitter yang dapat dijelaskan. Terlalu singkat menyebabkan pengiriman ulang yang tumpang tindih; terlalu lama menunda pemulihan. Batasi juga perolehan record per partisi dan koordinasikan semafor worker, connection pool database, serta kuota API eksternal. Pantau lock aktif, lock timeout, distribusi upaya pengiriman, reject, dan latensi penyelesaian end-to-end secara bersamaan.
4. Nyatakan kembali jaminan pengurutan dan duplikasi
Penjelasan Kafka sering kali mengubah “terurut di dalam partisi” menjadi “pemrosesan bisnis terurut.” Anggota Share Group dapat memperoleh record secara bersamaan, sehingga urutan penyelesaian untuk satu key mungkin berbeda dari urutan penulisan; release dan pengiriman ulang memperbesar perbedaan tersebut. Jika urutan penting, terapkan serialisasi tingkat key, pemeriksaan versi, atau state machine di aplikasi. Jangan hanya menjawab dengan “Kafka itu terurut.”
Exactly-once juga tidak muncul secara otomatis dari jenis grup. Telusuri batasan antara akuisisi record, penulisan bisnis, dan acknowledgement. Database eksternal atau layanan pembayaran tetap memerlukan key idempotensi, batasan deduplikasi, atau transactional outbox. Jika kombinasi tersebut tidak didukung, nyatakan bahwa desainnya adalah at-least-once dengan idempotensi daripada menyebutnya exactly-once.
5. Rencanakan migrasi dan rollback
Verifikasi versi broker, API klien, konfigurasi grup, ACL, metrik, dan perintah operasional. Kemudian lakukan uji beban pada topik terpisah atau beban kerja kecil. Injeksikan kegagalan: crash setelah akuisisi, pemrosesan melebihi durasi lock, reject berulang, restart broker, dan perpindahan koordinator. Catat business key, upaya ke-berapa, status, dan timestamp untuk setiap record.
Jika konsumen lama bergantung pada pengurutan atau transaksi, jangan ubah grup yang sama secara in-place. Salin pekerjaan ke topik khusus dan biarkan grup baru menerima traffic secara bertahap; jaga agar jalur lama tetap dapat di-replay hingga tingkat kesalahan, efek samping duplikat, dan latensi memenuhi kriteria (gates). Rollback dilakukan dengan menghentikan akuisisi baru dan membiarkan jalur lama mengonsumsi record yang belum dimigrasi. Dua jalur aktif tidak boleh mengeksekusi efek samping yang sama tanpa batasan deduplikasi yang eksplisit.
Contoh jawaban berkualitas tinggi
“Saya akan mulai dengan menanyakan apakah pekerjaan boleh selesai di luar urutan, apakah pemrosesan bersifat idempoten, dan apakah broker serta klien yang di-deploy mendukung KIP-932. Share Group memperlakukan record topik independen sebagai pekerjaan kooperatif: beberapa anggota dapat memperoleh record berbeda dari satu partisi, jumlah anggota dapat melebihi jumlah partisi, dan setiap record memiliki jalur acknowledge, release, reject, dan lock-expiry. Hal ini mengubah intuisi alokasi dan pengurutan grup tradisional, sehingga saya akan mempertahankan Consumer Group atau menambahkan pemeriksaan versi ketika suatu business key memerlukan urutan.
Saya akan menetapkan key idempotensi untuk setiap record, menentukan lock akuisisi dari waktu pemrosesan p99, serta membatasi lock aktif dan konkurensi downstream. Kegagalan sementara di-release dengan backoff; data rusak yang deterministik di-reject ke karantina; ambang batas upaya pengiriman menghentikan retry otomatis. Saya akan memantau acquire, acknowledge, release, reject, timeout, efek samping duplikat, dan latensi penyelesaian. Sebelum migrasi, saya akan memverifikasi versi, ACL, perilaku klien, dan kegagalan yang diinjeksikan pada topik terpisah. Kecuali jika akuisisi record, penulisan bisnis, dan acknowledgement berbagi satu batasan transaksi yang terbukti, saya akan menyebut desain ini sebagai at-least-once ditambah idempotensi, bukan exactly-once.”
Kesalahan umum
- Menyebut Share Group sebagai klona RabbitMQ → penyimpanan, replay, dan administrasi berbeda → hanya janjikan semantik akuisisi kooperatif dan acknowledgement yang didokumentasikan oleh KIP-932.
- Membatasi worker sejumlah partisi → Share Group memungkinkan beberapa anggota memproses satu partisi → batasi konkurensi berdasarkan lock, kapasitas downstream, dan latensi end-to-end.
- Mengasumsikan urutan key tetap terjaga → akuisisi konkuren dan pengiriman ulang mengubah urutan penyelesaian → serialisasikan key atau periksa versi ketika urutan menjadi kebutuhan.
- Melakukan acknowledgement tanpa idempotensi → crash atau lock yang kedaluwarsa dapat mengirim ulang record → lakukan deduplikasi berdasarkan business key sebelum acknowledgement.
- Melakukan release pada poison record tanpa henti → retry menghabiskan lock dan anggaran downstream → hentikan retry otomatis berdasarkan jenis error, jumlah percobaan, dan kebijakan karantina.
- Memperlakukan 30 detik sebagai jaminan → konfigurasi broker dan latensi pemrosesan berbeda-beda → uji pengaturan lock yang di-deploy terhadap p99.
Pertanyaan lanjutan dan jawabannya
Bagaimana jika event untuk satu pesanan harus diurutkan secara ketat?
Jangan beralih langsung ke Share Group. Pertahankan Consumer Group yang dipartisi berdasarkan ID pesanan, atau gunakan state machine yang diserialisasi pada tingkat aplikasi. Jika akuisisi bersama adalah keharusan, tambahkan pemeriksaan versi, validasi prasyarat, dan penataan ulang kegagalan, serta sadari kompleksitas tambahannya.
Bagaimana jika konsumen mengalami hang selama dua menit setelah akuisisi?
Tetapkan lock sedikit di atas p99 normal dan buat peringatan pada lock timeout. Izinkan pengiriman ulang setelah masa berlaku berakhir, tetapi wajibkan penanganan bisnis yang idempoten. Untuk pekerjaan yang lama, bagi menjadi langkah-langkah yang dapat dilanjutkan (resumable) atau gunakan lease eksternal daripada memperpanjang lock tanpa batas.
Bagaimana Anda menangani lima kegagalan skema berturut-turut?
Perlakukan sebagai kesalahan deterministik: reject setelah mencapai ambang batas dan tulis payload, versi skema, serta alasannya ke karantina. Setelah konsumen diperbaiki, putar ulang (replay) di bawah prosedur yang terkendali. Jangan biarkan alur kerja utama terus mencoba ulang tanpa batas.
Sistem saat ini mengandalkan transaksi Kafka. Bisakah langsung beralih?
Daftar batasan baca, pemrosesan, dan tulis dari transaksi tersebut, lalu verifikasi dukungan klien dan transaksi Share Group yang sebenarnya. Jika efek samping eksternal berada di luar transaksi yang sama, gunakan outbox, key idempotensi, dan kompensasi. Pertahankan Consumer Group jika dukungannya belum terbukti.
Bagaimana Anda membuktikan bahwa migrasi tidak menagih biaya ganda kepada pelanggan?
Catat setiap eksekusi di bawah business key unik dengan batasan deduplikasi. Injeksikan crash, lock kedaluwarsa, retry, dan rollback, lalu bandingkan jumlah eksekusi dan acknowledgement. Perluas traffic hanya jika invarian jumlah efek samping, latensi, dan tingkat kesalahan tetap terpenuhi.