Petunjuk dan konteks
Inti permasalahannya adalah isolasi performa dan keadilan, bukan sekadar menambahkan tenantId. Layanan ini menerima tugas laporan asinkron yang mengonsumsi antrean, CPU, pemindaian database, penyimpanan objek, dan bandwidth unduhan. Lonjakan di akhir bulan membuat beberapa tenant menjadi bising (noisy). Mulailah dengan menentukan sasaran layanan, lalu jelaskan apa yang dibagikan dan apa yang diisolasi.
Asumsikan tenant hanya dapat membaca datanya sendiri, laporan dapat selesai secara asinkron, dan penundaan sementara lebih disukai daripada kebocoran data antar-tenant. Enterprise tenant mungkin memiliki paket, wilayah, dan kebijakan retensi yang berbeda; kepatuhan, residensi data, dan kapasitas khusus adalah batasan mutlak yang harus diperjelas. Keadilan tidak berarti throughput yang sama selamanya: prioritas kontrak dan keamanan dapat memiliki bobot eksplisit yang dapat diaudit.
Skenario ini cocok untuk wawancara backend, platform, SRE, dan system design. AWS menghadirkan shuffle sharding sebagai pola isolasi multi-tenant inti, sementara materi system design publik memperlakukan isolasi tenant, kuota, dan noisy neighbors sebagai perhatian desain yang umum. Pertanyaan ini berfokus pada penjadwalan dan blast radius daripada rangkaian fitur SaaS yang lengkap.
Yang dinilai oleh pewawancara
Pertama, dapatkah Anda mengidentifikasi setiap permukaan isolasi? Identitas tenant, tugas (jobs), antrean, worker, koneksi database, cache, penyimpanan objek, dan egress semuanya dapat dibagikan; hanya mengisolasi ingress memungkinkan gangguan menembus ke downstream.
Kedua, dapatkah Anda membedakan kuota, penjadwalan yang adil, dan isolasi ketat? Token bucket tenant membatasi volume, fair queue memilih siapa yang berjalan berikutnya, dan shard atau pool khusus membatasi kegagalan. Masing-masing menyelesaikan masalah yang berbeda.
Ketiga, dapatkah Anda mempertimbangkan trade-off biaya antara tenant besar dan kecil? Dedikasi penuh menciptakan kapasitas yang menganggur dan beban operasional; pembagian penuh menciptakan perebutan sumber daya. Jawaban yang kuat memberikan tingkatan (tiers) dan pemicu migrasi.
Keempat, dapatkah Anda membuktikan isolasi? Ukur latensi, penolakan, usia antrean, konsumsi kuota, percobaan ulang (retries), dan drop berdasarkan tenant, antrean, dan lapisan sumber daya daripada mengandalkan rata-rata global.
Pertanyaan klarifikasi
- Apa sasaran layanannya? Tentukan p95, waktu tunggu maksimum, tingkat keberhasilan, dan ketersediaan regional untuk pekerjaan interaktif dan asinkron.
- Pekerjaan mana yang diprioritaskan? Tingkatan kontrak, pekerjaan manusia yang mendesak, laporan terjadwal, dan eksplorasi mungkin memiliki bobot yang berbeda.
- Di mana batasan data dan sumber daya? Apakah beberapa tenant memerlukan database, wilayah, kunci enkripsi, penyimpanan objek, atau worker pool terpisah?
- Bagaimana lonjakan dan kuota jangka panjang diukur? Tingkat pengiriman, pekerjaan konkuren, byte yang dipindai, waktu CPU, penyimpanan, atau egress?
- Bagaimana pengguna melihat antrean dan penolakan? Perkiraan waktu selesai, panduan percobaan ulang, penjelasan kuota, dan pelaporan admin harus eksplisit.
Jawaban 30 detik
“Pertama-tama saya menentukan sasaran latensi, keberhasilan, konkurensi, dan isolasi data per tenant dan paket, memisahkan kuota pengiriman, konkurensi yang sedang berjalan, dan anggaran downstream. Gateway mengautentikasi tenant, memvalidasi ukuran tugas dan kunci idempoten, lalu menulis ke antrean yang tahan lama (durable queue). Penjadwal menggunakan token bucket per tenant dan weighted fair queues; tenant yang bising atau teregulasi dapat dipindahkan ke worker pool khusus atau yang menggunakan shuffle-sharding. Pemindaian database, cache, penyimpanan objek, dan egress juga diukur. Selama kelebihan beban, tolak atau tunda pekerjaan berprioritas rendah dengan status yang sebenarnya dan dukungan pembatalan. Validasi dengan uji otorisasi lintas-tenant, injeksi gangguan (noise injection), latihan kegagalan, serta asersi p99, blast-radius, dan pemulihan per tenant.”
Jawaban langkah demi langkah
Langkah 1: Tentukan sumber daya dan sasaran layanan
Bagi alur laporan menjadi pengiriman, antrean, kueri, pembuatan, penulisan objek, dan pengunduhan. Tentukan sasaran yang terukur untuk masing-masing alur, seperti p95 pengiriman, usia antrean, waktu penyelesaian, keberhasilan pengunduhan, dan isolasi. Buat anggaran untuk CPU, memori, pemindaian, koneksi, slot antrean, permintaan objek, dan egress alih-alih hanya menyebutkan jumlah worker.
Langkah 2: Tetapkan konteks tenant yang tepercaya
Identitas tenant berasal dari kredensial yang diautentikasi dan otorisasi server, bukan dari tenantId yang disediakan pemanggil. Tugas, pesan antrean, kueri, path objek, kunci cache, dan token unduhan membawa konteks yang terverifikasi. Batasi bidang, rentang waktu, dan pemindaian maksimum sehingga tenant yang sah tidak dapat menghabiskan sumber daya bersama dengan kueri yang terlalu luas.
authenticated principal
-> authorize tenant and report definition
-> assign quota class and priority
-> enqueue {tenantId, taskId, costEstimate, deadline}
-> every worker and storage call re-checks tenant scopeLangkah 3: Pilih tingkatan isolasi
Tenant kecil dapat berbagi antrean dan worker dengan kuota tenant, batas konkurensi, dan penjadwalan yang adil. Tenant bervolume tinggi atau teregulasi dapat menerima antrean khusus, partisi, skema database, kunci enkripsi, atau worker pool khusus. AWS shuffle sharding memetakan setiap tenant ke kombinasi worker sehingga satu kegagalan worker memengaruhi lebih sedikit tenant; ini membatasi blast radius sambil tetap mempertahankan efisiensi berbagi sumber daya.
Langkah 4: Rancang kuota dan penjadwalan yang adil
Gunakan token bucket pengiriman untuk lonjakan ingress, batas konkurensi untuk pekerjaan yang sedang berjalan (in-flight), dan anggaran biaya untuk byte yang dipindai atau CPU. Weighted fair queue atau antrean virtual per tenant mencegah satu tenant mendominasi setiap worker; di dalam tenant, urutkan berdasarkan prioritas, batas waktu, dan usia antrean. Penolakan harus berupa status kelebihan beban sementara atau kuota yang dapat dijelaskan, bukan undangan untuk mencoba ulang tanpa henti.
| Kontrol | Batasan | Tujuan | Saat terlampaui |
|---|---|---|---|
| Submission bucket | Tingkat dan lonjakan per tenant | Membatasi puncak ingress | Tunda atau kembalikan status yang dapat dicoba ulang |
| In-flight cap | Pekerjaan yang sedang berjalan | Mencegah satu tenant memenuhi worker | Masukkan antrean dan tampilkan perkiraan waktu tunggu |
| Cost budget | Byte terpindai, CPU, memori | Menghentikan tugas besar agar tidak merusak downstream | Batalkan, bagi tugas, atau persempit rentang |
| Weighted fair queue | Bagian dispatch tenant | Mencegah starvation | Weighted round-robin dengan prioritas usia antrean |
| Dedicated shard | Tenant bervolume tinggi atau teregulasi | Membatasi dampak performa dan kegagalan | Pindahkan ke pool terisolasi atau lakukan degradasi |
Langkah 5: Lindungi sumber daya downstream
Mulai pekerjaan hanya setelah penjadwal memiliki anggaran database, cache, dan penyimpanan objek. Gunakan replika baca, rentang waktu, dan batas pemindaian untuk laporan; partisikan hasil berdasarkan tenant dan wilayah serta terbitkan otorisasi unduhan berumur pendek. Jika koneksi, cache, thread, dan egress tetap dibagi secara global, keadilan di ingress tidak dapat mencegah starvation di downstream. Berikan batasan konkurensi dan antrean terbatas tersendiri untuk dependensi kritis.
Langkah 6: Tangani lonjakan, kegagalan, dan pemulihan
Pertahankan state tugas, snapshot kuota, kunci idempoten, dan pembatalan. Worker yang mengalami crash dapat mencoba kembali, tetapi penulisan hasil harus idempoten melalui versi atau result key. Saat suatu dependensi tidak tersedia, jeda hanya kelas pekerjaan yang terpengaruh, pertahankan usia antrean dan estimasi, serta hindari gelombang percobaan ulang massal (retry storm). Saat pemulihan, tingkatkan penerimaan secara bertahap per tenant dan prioritas sambil memantau p99, error, dan kuota alih-alih melepaskan semua backlog sekaligus.
Langkah 7: Skalakan, migrasikan, dan validasi
Lakukan penskalaan berdasarkan throughput yang berguna, usia antrean, utilisasi sumber daya, dan bobot tenant, bukan hanya rata-rata CPU. Saat memindahkan tenant dari pool bersama ke shard khusus, pertahankan state tugas dan path hasil yang idempoten, beralihlah secara bertahap, dan sediakan opsi rollback. Uji otorisasi lintas-tenant, injeksi gangguan, kegagalan satu worker, database yang lambat, pemulihan antrean, pembatalan, dan migrasi tenant besar; setiap pengujian memastikan bahwa tenant lain tetap memenuhi sasaran mereka.
Contoh jawaban berkualitas tinggi
“Saya akan membagi laporan menjadi pengiriman, antrean, kueri, pembuatan, penyimpanan, dan pengunduhan, serta menetapkan sasaran latensi, keberhasilan, dan isolasi untuk masing-masing alur. Identitas tenant berasal dari konteks yang diautentikasi dan server mengotorisasi ulang definisi laporan; bidang tenant dalam request hanyalah input, bukan batas keamanan. Tugas masuk ke antrean yang tahan lama dengan identitas tenant, estimasi biaya, kunci idempoten, dan tenggat waktu.
Tenant kecil berbagi worker, tetapi masing-masing memiliki kuota tingkat pengiriman, pekerjaan in-flight, byte yang dipindai, dan penyimpanan. Penjadwalan adil berbobot (weighted fair scheduling) dengan prioritas usia antrean mencegah lonjakan akhir bulan mendominasi setiap worker. Tenant bervolume tinggi atau teregulasi dapat dipindahkan ke antrean khusus, partisi, atau worker pool dengan shuffle-sharding untuk mengurangi blast radius jika terjadi kegagalan worker atau tenant yang terlalu aktif. Koneksi database, cache, penyimpanan objek, dan egress juga menerima anggaran per tenant atau per kelas.
Jika kuota terlampaui, saya mengembalikan status antrean atau kelebihan beban sementara yang transparan dan mendukung pembatalan; klien tidak diizinkan mencoba ulang terus-menerus. Worker menggunakan kunci hasil yang idempoten, sementara kegagalan dependensi hanya menjeda pekerjaan yang terpengaruh dan pemulihan ditingkatkan secara bertahap berdasarkan tenant dan prioritas.
Saya akan memvalidasinya dengan uji akses lintas-tenant, lonjakan dari single-tenant, simulasi kerusakan worker dan database, pemutaran ulang antrean, pembatalan, dan latihan migrasi. Saya akan memeriksa p99, usia antrean, tingkat penolakan, penggunaan sumber daya, dan asersi kebocoran untuk setiap tenant. Saya hanya akan memperluas pool isolasi atau menyesuaikan bobot setelah tenant kecil maupun tenant tingkat tinggi memenuhi sasaran layanan mereka.”
Kesalahan umum
- Mempercayai
tenantIddari request → Pemanggil dapat memalsukan scope → Dapatkan dari autentikasi dan periksa ulang di downstream. - Memberikan satu worker tetap untuk setiap tenant → Kapasitas menganggur meningkat dan kegagalan tetap menyebar → Gunakan tingkatan risiko dan kombinasi shard jika diperlukan.
- Hanya membatasi tingkat pengiriman → Pekerjaan in-flight tetap menghabiskan downstream → Batasi juga konkurensi, biaya, dan dependensi.
- Menggunakan rata-rata global untuk keadilan → Tail latency tenant kecil menjadi tersembunyi → Catat p95, p99, antrean, dan penolakan berdasarkan tenant.
- Mencoba ulang tanpa henti saat beban berlebih → Amplifikasi percobaan ulang meruntuhkan layanan → Kembalikan status eksplisit, percobaan ulang idempoten, dan anggaran bersama.
- Menambah worker tanpa anggaran database → Dependensi menjadi bottleneck → Buat anggaran untuk setiap lapisan sumber daya secara end-to-end.
- Melepaskan semua backlog sekaligus saat pemulihan → Puncak beban baru akan terbentuk → Gunakan histeresis dan penerimaan bertahap.
- Migrasi tanpa state yang idempoten → Pekerjaan terduplikasi atau hasil hilang → Gunakan versi, kunci hasil, dan rollback.
Pertanyaan lanjutan dan tanggapan
Pertanyaan lanjutan 1: Apa perbedaan shuffle sharding dengan sharding biasa?
Sharding biasa umumnya menempatkan tenant pada satu shard tetap, sehingga kegagalan shard berdampak pada semua tenant di sana. Shuffle sharding memetakan setiap tenant ke kombinasi worker dengan tumpang tindih terbatas, sehingga memperkecil kelompok yang terpengaruh oleh kegagalan satu worker. Pendekatan ini memerlukan perhatian tambahan terkait kapasitas, rebalancing, dan migrasi hot-tenant.
Pertanyaan lanjutan 2: Bisakah tenant premium melewati penjadwalan yang adil?
Berikan bobot kontrak atau langganan berbayar yang eksplisit, tetapi tetap pertahankan batas total kapasitas, isolasi, dan keamanan. Cadangkan anggaran untuk pekerjaan premium sambil tetap mencatat sasaran layanan minimum bagi tenant biasa; "prioritas" tidak boleh berarti preemption tanpa batas.
Pertanyaan lanjutan 3: Bagaimana jika satu laporan memindai seluruh database?
Perkirakan biaya selama parsing dan pembuatan query plan, wajibkan rentang waktu, batasi byte dan konkurensi, serta bagi, tunda, atau tolak pekerjaan yang melebihi anggaran. Memperbesar pool database hanya memindahkan tekanan ke penyimpanan dan bukan merupakan solusi tuntas.
Pertanyaan lanjutan 4: Bagaimana cara membuktikan tidak ada kebocoran lintas-tenant?
Bangun matriks akses dari prinsipal yang diautentikasi di seluruh API, pemutaran ulang antrean, worker, cache, path objek, ekspor, dan alat admin. Tambahkan pengujian negatif sehingga konteks yang hilang atau dipalsukan akan ditolak secara default, serta lakukan asersi pada label tenant dan konten pada hasil nyata.