Topik wawancara representatif

Wawancara System Design: Bagaimana Cara Mengisolasi Noisy Tenant dan Menjadwalkan secara Adil?

Desain sistemSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Rancang layanan pelaporan asinkron untuk ribuan enterprise tenant. Beberapa tenant mengirimkan lonjakan ekspor besar di akhir bulan, tetapi hal tersebut tidak boleh merusak latensi atau ketersediaan tenant lainnya. Jelaskan isolasi tenant, kuota, antrean, penjadwalan, penyimpanan, degradasi, penskalaan, dan validasi.

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.

text
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 scope

Langkah 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.

KontrolBatasanTujuanSaat terlampaui
Submission bucketTingkat dan lonjakan per tenantMembatasi puncak ingressTunda atau kembalikan status yang dapat dicoba ulang
In-flight capPekerjaan yang sedang berjalanMencegah satu tenant memenuhi workerMasukkan antrean dan tampilkan perkiraan waktu tunggu
Cost budgetByte terpindai, CPU, memoriMenghentikan tugas besar agar tidak merusak downstreamBatalkan, bagi tugas, atau persempit rentang
Weighted fair queueBagian dispatch tenantMencegah starvationWeighted round-robin dengan prioritas usia antrean
Dedicated shardTenant bervolume tinggi atau teregulasiMembatasi dampak performa dan kegagalanPindahkan 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 tenantId dari 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.

Sumber publik

Pertanyaan terkait

Alat wawancara terkait

Gunakan Jawab untuk jawaban desain sistem

Perjelas persyaratan terlebih dahulu, lalu lanjutkan dengan skala, arsitektur, pilihan komponen, dan trade-off.

Lihat alat