Petunjuk dan ruang lingkup
Asumsikan 20.000 tenant dan 1 juta operasi per jam, dengan lonjakan singkat 10x dan keputusan otorisasi p95 di bawah 100 ms. Pelanggan membeli kredit sebelum menjalankan operasi. Setiap operasi memiliki biaya variabel, permintaan dapat tiba secara konkuren, dan pengiriman peristiwa penggunaan bersifat at-least-once. Desain harus mencegah saldo negatif dan penagihan ganda sembari mempertahankan jejak audit. Ini adalah buku besar nilai yang dibeli, bukan rate limiter atau sistem penagihan langganan berulang.
Apa yang sedang diuji oleh pewawancara
- Memisahkan pergerakan kredit yang tidak dapat diubah (immutable) dari model pembacaan saldo yang cepat.
- Membuat operasi authorize, capture, release, refund, dan grant menjadi idempoten.
- Menangani permintaan konkuren, peristiwa yang tertunda, percobaan ulang, kedaluwarsa, dan rekonsiliasi.
- Menjelaskan batasan konsistensi, tenant yang padat (hot tenants), observabilitas, dan pemulihan.
Pertanyaan klarifikasi yang perlu diajukan
Tanyakan apakah kredit dapat kedaluwarsa, apakah operasi yang gagal boleh melakukan reservasi lalu melepaskannya, bagaimana pengembalian dana disetujui, apakah biaya diketahui sebelum eksekusi, dan apakah satu tenant dapat membelanjakan kredit di beberapa wilayah. Konfirmasikan latensi keputusan yang diperlukan dan apakah otorisasi berlebih (over-authorization) sementara diizinkan.
Jawaban 30 detik
Saya akan menggunakan buku besar yang bersifat append-only dan immutable untuk pencatatan grant, reservation, capture, release, refund, dan expiration. Proyeksi saldo transaksional mendukung pembacaan cepat, sementara kunci idempotensi membuat setiap mutasi dapat diulang. Otorisasi secara atomik memeriksa kredit yang tersedia dan membuat reservasi dengan masa kedaluwarsa; pekerjaan yang berhasil akan meng-capture-nya, kegagalan akan melepaskannya (release), dan reclaimer menangani reservasi yang terbengkalai. Outbox, peristiwa yang dapat diputar ulang (replayable events), dan rekonsiliasi membandingkan proyeksi dengan buku besar serta memperbaiki pergeseran (drift) dengan entri kompensasi yang dapat diaudit.
Pembahasan mendalam langkah demi langkah
1. Memodelkan status kredit
Simpan satu kunci tenant/akun, unit kredit bilangan bulat, urutan buku besar, dan proyeksi yang berisi total yang diberikan (granted), dicadangkan (reserved), diambil (captured), dilepaskan (released), dikembalikan (refunded), dan kedaluwarsa (expired). Simpan setiap mutasi dengan operationid, idempotencykey, alasan, pelaku (actor), dan stempel waktu. Jangan pernah mengedit entri lama; koreksi dilakukan dengan menambahkan entri kompensasi (compensating entry).
2. Mengotorisasi tanpa pengeluaran ganda (double spending)
Gunakan satu transaksi atau pembaruan bersyarat yang dapat dilinearisasi (linearizable conditional update) untuk hot key milik tenant: buat reservasi hanya jika kredit yang tersedia setidaknya sebesar biaya yang diminta. Kunci idempotensi yang berulang mengembalikan keputusan awal; kunci yang digunakan kembali dengan parameter berbeda akan ditolak. Pertahankan kedaluwarsa reservasi dan transisi status secara bersyarat sehingga capture dan release tidak dapat sama-sama menang.
3. Menghubungkan eksekusi dan peristiwa
Permintaan bisnis membawa pengidentifikasi reservasi. Capture mengikuti keberhasilan yang terkonfirmasi; release mengikuti operasi yang gagal atau dibatalkan. Peristiwa penggunaan mungkin terduplikasi atau tertunda, sehingga konsumen melakukan deduplikasi berdasarkan event_id dan merekonsiliasi reservasi yang tidak diketahui alih-alih mengurangi penghitung secara membabi buta. Outbox mempublikasikan perubahan buku besar yang telah di-commit setelah transaksi.
4. Skala, alternatif, dan pemulihan
Partisi berdasarkan tenant, rute satu tenant ke satu home writer, dan isolasi tenant yang sangat padat dengan kontrol penerimaan (admission control) atau aliran perintah yang diserialisasi (serialized command stream). Transaksi relasional adalah pilihan yang lebih sederhana ketika tingkat penulisan setiap tenant moderat; aliran perintah berbasis event-sourcing lebih disukai untuk tenant yang sangat padat ketika pemutaran ulang dan pengurutan lebih penting daripada kesederhanaan kueri. Pembacaan dapat menggunakan replika hanya jika tingkat keusangannya (staleness) ditampilkan. Sweeper mengakhiri reservasi yang terbengkalai, dan pemutaran ulang membangun kembali proyeksi dari buku besar. Peringatan mencakup ketersediaan negatif, capture-after-expiry, keterlambatan pemutaran ulang (replay lag), dan perbedaan rekonsiliasi.
Contoh jawaban yang kuat
Saya akan mengklarifikasi kedaluwarsa, wewenang pengembalian dana, pembelanjaan lintas wilayah, dan apakah biaya diketahui sebelum eksekusi. Sumber kebenaran tunggal (source of truth) adalah buku besar per-tenant yang tidak dapat diubah; tabel saldo adalah proyeksi yang dapat dibangun kembali. authorize mencadangkan biaya secara atomik di bawah kunci idempotensi dan masa kedaluwarsa, capture mengonversi reservasi tersebut setelah berhasil, dan release atau kedaluwarsa mengembalikannya. Peristiwa duplikat atau tertunda di-deduplikasi dan direkonsiliasi. Penulisan berbasis tenant-affine menghindari pengeluaran ganda lintas wilayah; jika suatu wilayah harus beroperasi secara independen, wilayah tersebut menerima alokasi terbatas yang utangnya direkonsiliasi secara eksplisit. Setiap koreksi adalah entri kompensasi yang bersifat append-only.
Kesalahan umum
- Hanya menggunakan penghitung yang dapat diubah (mutable counter) → percobaan ulang dan pengembalian dana tidak dapat diaudit → tambahkan entri yang tidak dapat diubah dengan identitas operasi.
- Menagih saat permintaan diterima → pekerjaan yang gagal tetap menghabiskan kredit → cadangkan terlebih dahulu dan capture hanya setelah berhasil.
- Percobaan ulang diperlakukan sebagai konsumsi baru → satu operasi ditagih dua kali → gunakan kembali kunci idempotensi yang sama.
- Reservasi tidak pernah direklamasi → worker yang mogok (crash) mengunci kredit selamanya → tambahkan kedaluwarsa dan sweeper bersyarat.
- Pembacaan konsistensi akhir (eventually consistent) lintas wilayah → dua writer dapat membelanjakan secara berlebih → gunakan satu writer atau anggaran regional yang eksplisit.
- Mengedit baris lama untuk memperbaiki riwayat → jejak audit menjadi tidak dapat dipercaya → tambahkan entri kompensasi.
Pertanyaan lanjutan dan tanggapan
Klien mengalami batas waktu (timeout) setelah otorisasi. Apa yang terjadi?
Kueri reservasi atau coba lagi transisi berikutnya dengan kunci idempotensi yang sama. Jangan mengotorisasi lagi sampai reservasi awal di-capture, di-release, atau kedaluwarsa.
Bagaimana Anda memproses pengembalian dana setelah penutupan bulan?
Tambahkan entri pengembalian dana yang mereferensikan capture asli dan catatan persetujuan. Proyeksi meningkatkan kredit yang tersedia, sementara buku besar mempertahankan kedua peristiwa beserta urutannya.
Bisakah dua wilayah membelanjakan akun yang sama secara konkuren?
Lebih baik gunakan satu writer atau wilayah asal tenant untuk semantik tanpa pembelanjaan ganda yang ketat. Jika pembelanjaan lokal terbatas diperlukan, alokasikan anggaran regional yang eksplisit dan rekonsiliasi utangnya; nyatakan kelebihan sementara maksimum yang diizinkan.
Bagaimana Anda membuktikan bahwa saldonya benar?
Putar ulang buku besar secara berkala, bandingkan jumlah ketersediaan yang dihasilkan dengan proyeksi, dan bandingkan hasil capture dengan hasil operasi bisnis. Keluarkan entri kompensasi yang idempoten dan catatan audit untuk setiap perbaikan.