Topik temu duga representatif

Temu Duga Backend: Bagaimanakah anda mereka bentuk penomboran halaman kursor yang stabil untuk senarai besar yang sering berubah?

BackendSederhana
Pasukan Editorial Offer.ccDiterbitkan Dikemas kini

Soalan

Sebuah senarai dengan ratusan juta baris terus menerima operasi sisipan dan pemadaman, dan halaman mengandungi data pendua atau jurang. Bagaimanakah anda mendiagnosisnya dan memilih antara OFFSET, penomboran halaman keyset, dan kursor pangkalan data?

Soalan dan konteks

Soalan ini menguji sama ada seorang jurutera backend boleh mengendalikan prestasi halaman dalam (deep-page), susunan yang stabil di bawah operasi penulisan serentak, dan kontrak kursor yang eksplisit pada masa yang sama. Andaikan klien melayari pesanan atau suapan yang berubah mengikut susunan masa menurun, 50 baris setiap halaman, dengan baris baharu tiba secara berterusan; ia kebanyakannya memerlukan halaman seterusnya dan bukannya lompatan halaman sewenang-wenangnya.

Ia sesuai untuk peranan backend, perkhidmatan data dan platform. Jangan mengumumkan bahawa kursor sentiasa lebih pantas. Mula-mula jelaskan susunan, lompatan halaman, eksport, ketekalan, semantik pemadaman, replika dan indeks kerana setiap kekangan mengubah pilihan penyelesaian.

Perkara yang dinilai oleh penemu duga

Jawapan yang mantap menjelaskan sebab OFFSET yang dalam mengimbas dan membuang baris terdahulu, sebab kunci isihan yang tidak unik beralih di bawah penulisan serentak, dan sebab penomboran halaman keyset memerlukan jumlah susunan yang stabil dan indeks yang sepadan. Ia juga membezakan token keyset tanpa keadaan (stateless) daripada kursor pangkalan data yang memegang transaksi, dan mencadangkan ujian untuk pendua, jurang, baris sempadan yang dipadam dan token palsu.

Soalan penjelasan untuk ditanya

  • Adakah pengguna mesti melompat ke halaman N atau melihat jumlah kiraan? Penomboran halaman keyset tulen tidak menyediakan perkara itu secara langsung.
  • Apakah susunan isihan? Adakah cap masa unik dan tidak boleh diubah, atau adakah ia memerlukan ID unik sebagai pemutus seri?
  • Adakah klien mahukan paparan langsung (live view) atau syot kilat (snapshot) untuk satu traversal? Sisipan dan pemadaman kelihatan berbeza di bawah setiap satu.
  • Adakah pertanyaan merentasi replika, shard, atau penapis penyewa? Indeks dan token mesti mengikat syarat tersebut.
  • Bolehkah klien menyahkod, mengubah suai, atau memainkan semula kursor? Perkara tersebut menentukan pemeteraian, tamat tempoh dan pemversian.

Rangka kerja jawapan 30 saat

“Saya terlebih dahulu menjelaskan susunan, lompatan halaman dan semantik ketekalan. Untuk senarai besar yang berubah-ubah, saya akan menggunakan penomboran halaman keyset dengan pemutus seri yang unik, seperti created_at DESC, id DESC, disokong oleh indeks komposit yang sepadan; permintaan seterusnya membawa kunci isihan baris terakhir dan bukannya OFFSET yang dalam. Kursor mengekod penapis, versi isihan dan sempadan, kemudian ditandatangani dan diberikan masa tamat tempoh. Jika traversal memerlukan syot kilat tetap, saya akan mempertimbangkan cap masa atau kursor pangkalan data transaksi dan menerangkan kos sumbernya. Saya akan mengesahkan kontrak dengan sisipan serentak, pemadaman, cap masa pendua dan token yang diusik.”

Jawapan langkah demi langkah

Langkah 1: Tentukan kontrak penomboran halaman

Tentukan had limit, susunan lalai, next_cursor, has_more dan penapis. Susunan yang stabil memerlukan susunan penuh (total order); menyusun mengikut created_at sahaja adalah kabur apabila beberapa baris berkongsi cap masa yang sama, jadi tambahkan ID unik yang tidak boleh diubah. Jika klien memerlukan halaman sebelumnya, reka bentuk perbandingan terbalik dan pengendalian sempadan secara eksplisit dan bukannya sekadar menterbalikkan pertanyaan halaman seterusnya.

Langkah 2: Terangkan prestasi dan peralihan OFFSET

OFFSET k LIMIT n biasanya memerlukan pangkalan data mencari dan melangkau k baris sebelumnya, jadi kerja halaman dalam meningkat mengikut k. Jika sisipan atau pemadaman berlaku sebelum halaman yang telah dibaca, ofset seterusnya beralih dan boleh menghasilkan pendua atau jurang. Senarai pentadbir yang kecil dan kebanyakannya statik yang memerlukan lompatan halaman boleh menerima OFFSET, tetapi hadkan kedalamannya dan sahkan kosnya dengan pelan pelaksanaan.

Langkah 3: Laksanakan keyset ke atas jumlah susunan yang stabil

Untuk (created_at, id) menurun, halaman pertama tidak mempunyai sempadan dan halaman seterusnya menggunakan kunci baris terakhir:

sql
-- first page
SELECT id, title, created_at
FROM posts
ORDER BY created_at DESC, id DESC
LIMIT 50;

-- next page: boundary comes from the last returned row
SELECT id, title, created_at
FROM posts
WHERE (created_at, id) < (:last_created_at, :last_id)
ORDER BY created_at DESC, id DESC
LIMIT 50;

Pertanyaan mencari daripada sempadan indeks dan mengimbas bilangan baris yang terhad dan bukannya melangkau setiap halaman terdahulu. Susunan lajur indeks komposit, penapis dan arah mesti sepadan dengan pertanyaan; jika tidak, pertanyaan keyset yang secara teorinya baik masih boleh mengimbas julat yang besar.

Langkah 4: Reka bentuk token kursor yang boleh disahkan

Jangan anggap ofset dalaman sebagai kursor. Sertakan kunci sempadan, ringkasan penapis, versi isihan dan tamat tempoh; tandatangani token atau gunakan penyulitan yang disahkan supaya klien tidak boleh mengubah suainya. Apabila diterima, sahkan versi, penyewa dan penapis terhadap permintaan tersebut. Jika susunan berubah, tolak versi lama atau mulakan semula secara eksplisit daripada mentafsir token yang sama di bawah susunan yang berbeza.

Langkah 5: Pilih semantik langsung atau syot kilat

Penomboran halaman keyset langsung membolehkan baris baharu muncul di bahagian atas; baris yang sudah melepasi sempadan biasanya tidak berulang. Memadamkan baris sempadan tidak menyebabkannya muncul semula, walaupun jumlah kiraan berubah. Untuk eksport atau audit yang memerlukan set tetap, sertakan cap masa baca, versi syot kilat atau kursor pangkalan data dalam kontrak. Kursor pangkalan data boleh memegang transaksi dan sumber, jadi ia tidak semestinya sesuai untuk penomboran halaman HTTP jangka panjang.

Langkah 6: Kendalikan replika, shard dan baris sempadan

Kelengahan replika boleh menyembunyikan sementara baris yang telah dikembalikan oleh nod utama. Pinkan laluan, bawa sempadan masa yang disahkan, atau dokumentasikan ketekalan akhirnya (eventual consistency). Merentasi shard, setiap shard boleh menghasilkan keyset tempatan dan perkhidmatan boleh melaksanakan gabungan k-hala (k-way merge) yang menyedari kursor. Uji pemadaman baris sempadan akhir, cap masa yang sama dan perubahan penapis.

Langkah 7: Sahkan prestasi dan ketepatan

Pemeriksaan prestasi merangkumi imbasan baris halaman dalam, pendam P95 dan penggunaan indeks. Ujian ketepatan menyisip, memadam dan mengemas kini baris antara permintaan serta mengesahkan tingkah laku pendua dan jurang yang dijanjikan. Log penapis setiap halaman, versi isihan, kunci pertama dan terakhir serta versi token supaya peralihan pengeluaran boleh dipetakan ke sempadan yang konkrit.

Contoh jawapan yang mantap

“Mula-mula saya akan menjelaskan sama ada pengguna memerlukan lompatan halaman, jumlah kiraan atau syot kilat tetap, dan sama ada medan isihan adalah unik. Untuk senarai yang ditulis secara berterusan yang kebanyakannya dilayari ke hadapan, saya akan memilih penomboran halaman keyset: gunakan created_at yang tidak boleh diubah ditambah id yang unik untuk susunan penuh dan indeks komposit, kemudian gunakan dua kunci baris terakhir sebagai sempadan julat seterusnya. Halaman dalam tidak mengimbas dan membuang semua baris sebelumnya, dan sisipan sebelum sempadan tidak mengalihkan setiap halaman berikutnya.

Saya akan mengekod penapis, versi isihan, kunci sempadan dan tamat tempoh dalam token yang ditandatangani, kemudian memerlukan penyewa dan penapis token sepadan dengan permintaan. Di bawah semantik langsung, baris baharu muncul di bahagian atas; untuk hasil tetap tahap audit, saya akan mempertimbangkan cap masa atau kursor transaksi terkawal dan menerangkan kos transaksi panjang. Dengan replika, saya akan mengepin penghalaan atau mendokumentasikan sempadan keterlihatan.

Akhir sekali, saya akan mengesahkan pelan pelaksanaan dan ujian keserentakan yang meliputi imbasan dalam, cap masa pendua, sisipan, pemadaman, kemas kini pada baris sempadan, kelengahan replika dan pengusikan token. Senarai pentadbir kecil yang mesti melompat halaman boleh mengekalkan OFFSET, tetapi saya akan mengehadkan kedalaman dan memantau kependaman.”

Kesilapan lazim

  • Mendakwa kursor sentiasa lebih pantas → mengabaikan lompatan dan kos transaksi panjang → bandingkan OFFSET, keyset dan kursor pangkalan data mengikut kekangan.
  • Menyusun mengikut masa sahaja → nilai seri mempunyai susunan yang tidak stabil → tambahkan ID unik yang tidak boleh diubah.
  • Meletakkan nombor ofset dalam token → halaman dalam masih beralih dan kos lebih tinggi → bawa sempadan isihan dan ringkasan penapis.
  • Membiarkan langsung/syot kilat tidak ditakrifkan → klien tidak dapat mentafsir sisipan atau pemadaman → nyatakan semantik keterlihatan dalam kontrak API.
  • Mengabaikan arah indeks dan penapis → keyset masih mengimbas banyak baris → sahkan indeks komposit dengan pelan pelaksanaan.
  • Menerima sebarang kursor klien → penyewa atau sempadan basi boleh dipalsukan → tandatangani, sahkan versi dan tamatkan tempoh token.

Soalan susulan dan jawapan

Soalan susulan 1: Pengguna mesti melompat ke halaman 500. Apakah yang anda lakukan?

Untuk senarai pentadbir yang kecil atau kebanyakannya statik, OFFSET yang dihadkan adalah munasabah. Untuk senarai yang besar, gunakan sempadan halaman yang telah dikira lebih awal atau penapis carian dan isihan supaya pengguna mencari kawasan yang diingini dan bukannya menjanjikan pendaman rendah pada kedalaman sewenang-wenangnya. Dokumentasikan had kos dan ketekalan bagi mana-mana pilihan.

Soalan susulan 2: created_at boleh diedit. Adakah kursor itu stabil?

Tidak. Gunakan masa penciptaan yang tidak boleh diubah ditambah ID unik, atau bekukan medan isihan yang boleh diubah dalam versi syot kilat. Jika perniagaan mesti menyusun mengikut medan yang boleh diubah, terima pergerakan dalam paparan langsung atau gunakan versi tetap dengan kos storan dan bacaan tambahan.

Soalan susulan 3: Replika yang ketinggalan menjadikan halaman seterusnya pendek. Bagaimanakah anda mengendalikannya?

Pinkan bacaan kepada nod utama atau replika yang sama mengikut keperluan ketekalan, atau bawa sempadan "tidak lebih awal daripada masa/LSN" dan kembalikan status eksplisit selepas tamat masa menunggu. Jangan senyap-senyap menganggap baris yang hilang sebagai penghujung senarai; bezakan ketidakkelihatan sementara daripada has_more=false.

Soalan susulan 4: Bagaimanakah anda membuktikan tiada pendua atau jurang?

Bina ujian keserentakan terkawal: baca halaman satu, sisip sebelum sempadan, padam baris sempadan, sisip kunci isihan yang sama dan kemas kini baris; kemudian periksa set ID unik, susunan dan keterlihatan yang dijanjikan. Log sempadan halaman, versi token dan pengecam syot kilat supaya kegagalan boleh dihasilkan semula pada sempadan yang tepat.

Sumber awam

Soalan berkaitan