Masalah dan Skop
Reka bentuk perkhidmatan carian tempat berhampiran global. Katalog ini mengandungi 50 juta restoran, kedai dan kemudahan awam. Pengguna membekalkan kedudukan semasa, jejari dari 500 meter hingga 50 kilometer, kategori dan penapis waktu operasi, kemudian menerima 20 hasil carian terdekat. Trafik carian memuncak pada 200,000 permintaan sesaat. Penciptaan, penempatan semula dan penutupan tempat memuncak pada 100 kemas kini sesaat. Pendam bacaan (read latency) mesti kekal di bawah 150 milisaat pada p99.
Masalah ini menganggap tempat sebagai entiti statik yang jarang berubah. Lokasi pemandu, kurier atau rakan setiap saat, pemadanan dan tugasan eksklusif adalah milik sistem lokasi dinamik yang berbeza. Jarak bermaksud jarak geografi di atas permukaan Bumi. Masa laluan, pemperibadian dan lelongan pengiklanan berada di luar skop teras. Semua kiraan dan SLO merupakan andaian temu duga.
Masalah utamanya ialah pertanyaan jejari dua dimensi. B-tree biasa bagi latitud dan longitud tidak boleh melompat terus ke setiap baris di dalam bulatan pertanyaan. Corak yang disyorkan mula-mula menggunakan indeks ruang (spatial index) atau grid diskret untuk mencipta superset calon, kemudian mengira jarak tepat, menapis, menyusun dan memotong (truncate). Pukulan sel hanyalah penapis kasar; berkongsi sel atau sel jiran tidak membuktikan bahawa sesuatu tempat berada di dalam jejari tersebut.
Perkara yang Dinilai oleh Penemu Duga
Isyarat pertama ialah mentakrifkan ketepatan sebelum komponen. Setiap hasil mesti berada di dalam jejari, melepasi penapis dan muncul dalam susunan terdekat didahulukan yang deterministik. Set calon mesti merangkumi tempat merentasi sempadan sel, dan jarak tepat mesti mengesahkan hasil carian kasar. Menanyakan geohash pengguna sahaja akan terlepas perniagaan yang berada berpuluh meter jauhnya merentasi tepi sel yang sewenang-wenangnya.
Isyarat kedua ialah memilih indeks berdasarkan corak kemas kini. Perniagaan statik boleh bermula dengan PostGIS GiST, R-tree atau indeks jarak natif pangkalan data. Apabila trafik bacaan dan penghalaan global mewajarkannya, tempat boleh dipetakan ke dalam sel H3, S2 atau geohash. Sekadar menyatakan "gunakan Redis GEO" tidak menerangkan liputan bulatan, resolusi, titik panas (hot spots) atau jarak tepat.
Isyarat ketiga ialah mengenali kecondongan ruang (spatial skew). Sel lautan dan luar bandar hampir kosong, manakala satu sel di pusat bandar mungkin sangat panas. Julat latitud-longitud yang seragam tidak menghasilkan serpihan (shard) yang seragam. Reka bentuk yang berguna menghalakan mengikut awalan ruang yang kasar, membelah sel yang padat dan menambah replika untuk sel yang kerap dibaca. Pertanyaan berjejari besar merentasi serpihan, jadi satu carian tidak boleh selalu diandaikan mengenai satu nod.
Akhir sekali, penomboran halaman, ketekalan dan kegagalan mesti selaras. Bagi penomboran halaman berasaskan jarak, koordinat pengguna, penapis, versi katalog, jarak terakhir dan ID tempat adalah sebahagian daripada kontrak kursor. Kemas kini atau masa tamat serpihan boleh mengubah set hasil. Jawapan yang kukuh mengisytiharkan semantik syot kilat (snapshot) atau usaha terbaik (best-effort) dan menjadikan hasil separa boleh dikenali.
Soalan untuk Dijelaskan Sebelum Menjawab
- Adakah lokasi bersifat statik atau bergerak secara berterusan? Kemuncak 100 kemas kini sesaat menyokong pengecaman cache dan pengindeksan tak segerak (asynchronous). Entiti yang bergerak memerlukan kesegaran yang lebih ketat, indeks yang dioptimumkan untuk penulisan dan ketekalan pemadanan.
- Adakah "terdekat" bermaksud jarak geografi atau masa perjalanan? Reka bentuk ini menggunakan jarak geografi. Masa perjalanan memerlukan graf jalan raya dan perkhidmatan ETA yang berasingan, biasanya digunakan pada set calon kasar yang kecil.
- Adakah hasil mesti lengkap, atau adakah 20 calon anggaran boleh diterima? Masalah ini memerlukan penapisan jejari yang betul dan 20 terdekat yang deterministik dalam kalangan tempat yang diindeks. Sel hanya boleh menjana calon.
- Berapa segarkah status waktu operasi yang diperlukan? Lokasi dan kategori boleh bertolak ansur dengan penyebaran skala minit. Jika penutupan sementara memerlukan beberapa saat, simpannya dalam tindanan (overlay) TTL pendek yang berasingan dan bukannya memberikan katalog statik satu janji yang bercampur-campur.
- Adakah penomboran halaman mendalam diperlukan? Carian berhampiran biasanya hanya memerlukan beberapa halaman. Reka bentuk ini menghadkan sesi hasil kepada 100 tempat. Mengeksport setiap hasil dalam lingkungan 50 kilometer memerlukan API tak segerak atau semakan imbas serantau.
- Bolehkah kegagalan rentas serpihan mengembalikan data separa? API penerokaan boleh mengembalikan
partial=truedengan rantau yang hilang. Pemanggil yang ketat boleh gagal dan mencuba semula. Data separa tidak boleh dipersembahkan sebagai set terdekat yang lengkap.
Jawapan 30-Saat
"Saya akan memisahkan laluan tulis katalog daripada laluan carian. Rekod tempat berversi memasuki katalog punca kebenaran (source-of-truth) dan mengemas kini indeks ruang secara tak segerak. Setiap tempat menyimpan koordinat tepat, sel penghalaan kasar dan sel resolusi carian. Sesuatu pertanyaan mengesahkan jejari dan penapisnya, kemudian menggunakan liputan H3, S2, geohash atau indeks jarak PostGIS untuk mendapatkan superset calon. Ia mengira jarak sfera yang tepat, menapis dan menyusun mengikut (distance, place_id) sebelum mengambil 20.
Awalan kasar menghala ke serpihan. Sel yang padat boleh dibelah, dan pertanyaan rentas sel melawat bilangan serpihan yang terhad secara selari sebelum penggabungan k-teratas global. Kunci cache merangkumi sel, baldi jejari, penapis dan versi katalog; pemindahan berversi membatalkan kesahan sel lama dan baharu. Kursor mengikat pertanyaan asal dan syot kilat katalog. Saya akan mengesahkan sempadan, garisan tarikh, kutub, bandar panas, penempatan semula, masa tamat serpihan dan cache lapuk sambil mengukur ketepatan dan p99."
Penerokaan Mendalam Langkah demi Langkah
Langkah 1: Tetapkan API, model dan invarian
API menerima jejari yang terhad, koordinat yang sah, penapis yang diluluskan dan saiz halaman yang kecil. Respons merangkumi jarak yang dikira, versi katalog, kelengkapan dan kursor kesinambungan.
GET /v1/places/nearby?lat=&lng=&radius_m=&category=&open_at=&limit=&cursor=
Place {
place_id, lat, lng, search_cell, routing_cell,
category, status, hours_version, location_version, updated_at
}
Cursor {
query_hash, catalog_version, last_distance_m, last_place_id
}Kekalkan empat invarian: setiap hasil memenuhi jejari dan penapis; penjanaan calon tidak boleh meninggalkan titik di dalam bulatan; susunan akhir ialah (distance_m, place_id); dan versi lokasi lama tidak boleh menimpa versi baharu. Koordinat menggunakan satu sistem rujukan yang diisytiharkan, menolak julat yang tidak sah dan menggunakan meter secara dalaman.
Langkah 2: Pilih indeks ruang paling mudah yang memenuhi sasaran
Versi pertama boleh menggunakan pangkalan data hubungan dengan indeks ruang. Pertanyaan jejari menggunakan bentuk sempadan yang boleh diindeks untuk mengurangkan set tersebut, kemudian fungsi jarak tepat untuk menapisnya. Dokumentasi rasmi earthdistance secara eksplisit menyatakan kotak yang boleh diindeks mengandungi beberapa titik di luar jarak bulatan besar yang diminta, jadi semakan jarak kedua diperlukan. Peraturan superset calon ini adalah bebas daripada mana-mana satu vendor.
Apabila satu topologi pangkalan data tidak dapat mengendalikan trafik bacaan global atau penghalaan ruang yang eksplisit diperlukan, kodkan setiap tempat ke dalam sel H3, S2 atau geohash dengan resolusi tetap. Tukarkan bulatan pertanyaan kepada set sel yang meliputi kawasan tersebut, baca senarai songsang (inverted list) setiap sel, nyahduplikasi dan perhalusi. Hierarki H3 menukar resolusi dengan cekap, tetapi pembendungan geografi merentasi sel induk dan anak mempunyai kebimbangan anggaran. Pengesahan titik ke titik yang tepat masih menentukan kemasukan.
Satu resolusi tetap mewujudkan masalah yang bertentangan: sel yang besar menguatkan calon, manakala sel yang kecil menyebabkan pertanyaan 50 kilometer membilang terlalu banyak sel. Pilih daripada set kecil resolusi yang dipratakrifkan berdasarkan jejari dan prakira tahap tersebut untuk setiap tempat, atau halakan jejari yang besar melalui indeks yang lebih kasar. Penguatan calon, pecahan keluar (fanout) dan ujian beban p99 menentukan tahap tersebut.
Langkah 3: Laksanakan carian calon dan k-teratas global
Perkhidmatan pertanyaan menukar bulatan kepada sel calon, merangkumi setiap sel yang bersilang dan bukannya bahagian tengah sahaja. Ia membaca ID tempat dan koordinat yang ditapis secara kasar daripada setiap sel secara selari di bawah tarikh akhir keseluruhan dan belanjawan bagi setiap serpihan. Ia menyahduplikasi mengikut place_id, mengira jarak geografi yang tepat, mengeluarkan titik di luar bulatan dan menggunakan penapis kebenaran, status dan kategori.
Setiap serpihan boleh mengembalikan k teratas tempatannya, tetapi pemotongan itu memerlukan bukti. Jika setiap serpihan menyusun mengikut jarak akhir yang sama dan mengembalikan sekurang-kurangnya k global, item serpihan k+1 tidak boleh memasuki k teratas global. Pengagregat bergabung dengan timbunan maksimum (max heap) bersaiz k. Kerja adalah linear dalam calon yang dikembalikan, dengan memori penggabungan O(k).
Jejari yang besar atau pusat bandar yang padat boleh menghasilkan terlalu banyak calon. Perkhidmatan menetapkan belanjawan calon tetapi tidak boleh memotong secara senyap dan mendakwa ketepatan. Ia boleh memilih grid yang lebih halus, menolak penapisan kategori ke bawah, berkembang dalam gelang sehingga 20 hasil wujud dan jarak minimum yang mungkin dari setiap rantau yang belum dicari melebihi hasil kedua puluh semasa, atau mengembalikan ralat had sumber yang eksplisit.
Langkah 4: Belanjawankan pemeringkatan/penserpihan, titik panas dan kapasiti
Petakan direktori sel kepada serpihan dengan routing_cell yang kasar, bukannya membuat serpihan secara rawak mengikut place_id, yang akan menyiarkan setiap pertanyaan ruang. Perkhidmatan direktori mengekalkan jadual penghalaan dan epok. Sesuatu pertanyaan menggunakan satu epok dan mencuba semula sekiranya berlaku perubahan penghalaan supaya pembelahan sel tidak mewujudkan jurang.
Jika satu rekod indeks carian termasuk ID, koordinat, medan penapis dan overhed dianggarkan pada 128 hingga 256 bait, 50 juta rekod memerlukan kira-kira 6 hingga 12 GiB sebelum replikasi, pelbagai resolusi dan overhed pangkalan data. Magnitud ini boleh dipisahkan dan disampaikan oleh nod yang dioptimumkan untuk bacaan, tetapi ia tidak membuktikan bahawa mana-mana pangkalan data tertentu akan memenuhi sasaran.
Pada 200,000 QPS dan purata ilustrasi enam bacaan sel, bahagian belakang menyaksikan kira-kira 1.2 juta bacaan sel sesaat. Pengecaman cache dan bacaan kelompok mesti mengurangkan operasi. Tambah replika berdasarkan kepanasan bacaan dan belah sel yang padat kepada sel anak. Penggabungan sel yang jarang hanya mengubah storan dan penghalaan; liputan geometri masih mengawal ketepatan.
Langkah 5: Jadikan penulisan, cache dan ketekalan menumpu
Selepas pengesahan pemilikan, perkhidmatan tempat mengemas kini rekod sumber dan menambah location_version. Peristiwa perubahan mengandungi sel lama, sel baharu dan versi. Pengguna indeks menulis versi baharu ke dalam sel baharu sebelum memadamkan sel lama. Operasi bacaan menyahduplikasi mengikut versi, menjadikan main semula selamat dan menghalang pemadaman yang tertunda daripada membiarkan data lapuk menang. Pemindahan rentas serpihan mendedahkan sela masa indeks yang terhad dan menumpu mengikut versi dan bukannya memerlukan transaksi teragih serta-merta.
Gunakan dua lapisan cache: ID calon sel-ke-calon dan objek tempat yang lengkap. Kunci calon merangkumi versi indeks, sel, kategori dan baldi status. Cache respons akhir juga mesti menyertakan baldi koordinat, baldi jejari, penapis dan versi katalog, jadi ia biasanya mempunyai kadar pukulan yang lebih rendah. Kemas kini membatalkan kesahan sel lama dan baharu, manakala TTL yang pendek mengehadkan peristiwa pembatalan sah yang hilang.
Jika open_at berubah setiap minit, jangan bersihkan setiap cache ruang pada setiap minit. Simpan calon statik dan peraturan operasi dalam cache, kemudian nilaikan peraturan semasa masa pertanyaan. Penutupan sementara berada dalam tindanan segar yang kecil. Oleh itu, perubahan keadaan waktu operasi tidak membina semula indeks geografi.
Langkah 6: Takrifkan penomboran halaman dan semantik kegagalan
Kursor mencincang koordinat, jejari, penapis dan catalog_version, kemudian menyimpan (distance_m, place_id) terakhir. Panggilan halaman seterusnya menolak parameter pertanyaan yang berbeza. Jika syot kilat jangka pendek disokong, ia membaca versi katalog yang sama. API usaha terbaik pula mendokumentasikan bahawa kemas kini serentak boleh mewujudkan pertindihan atau ketinggalan dan membiarkan klien menyahduplikasi ID.
Setiap serpihan menerima tarikh akhir yang lebih pendek daripada sasaran hujung ke hujung 150 milisaat. Selepas satu serpihan tamat masa, respons tersebut tidak boleh dipanggil 20 terdekat global kerana serpihan yang hilang mungkin mengandungi tempat yang lebih dekat. API penerokaan boleh mengembalikan partial=true, sel yang hilang dan kursor percubaan semula. Klien yang ketat menerima hasil tidak tersedia yang jelas. Pemutus litar (circuit breaking) mengasingkan serpihan yang gagal, bukan keseluruhan indeks global.
Penyebaran serantau harus mengutamakan replika bacaan tempatan yang lengkap atau partisi geografi. Dasar rentas sempadan mengawal metadata tempat dan audit, manakala koordinat perniagaan awam sekalipun memerlukan sumber yang dibenarkan. Pengambilalihan kegagalan (failover) hanya boleh menggunakan rantau dengan indeks yang cukup segar dan mesti mengembalikan as_of; ia tidak boleh berundur kepada imbasan jadual katalog semasa insiden berlaku.
Langkah 7: Sahkan dengan contoh lawan geometri dan kerosakan
Untuk data ujian kecil, gunakan jarak tepat brute-force sebagai orakel. Jana titik dan bulatan rawak dan bandingkan set hasil. Sasarkan tepi dan bucu sel, longitud positif dan negatif 180 darjah, kawasan kutub, titik tepat pada jejari, koordinat pendua, sifar hasil, kedudukan seri 20 dan 21, dan penempatan semula merentasi sel. Pastikan tiada negatif palsu, tiada titik luar dan pemutus seri yang stabil.
Ujian beban merangkumi rantau kosong, bandar biasa dan titik panas yang sangat padat secara berasingan. Ukur pecahan keluar sel, penguatan calon, pengiraan jarak tepat, kadar pukulan cache, p95/p99 serpihan, masa penggabungan dan p99 hujung ke hujung. Kerosakan termasuk satu replika sel yang perlahan, perubahan epok penghalaan, pembatalan sah yang hilang, main semula pengguna, pemindahan rentas serpihan yang terganggu dan pengambilalihan kegagalan serantau.
Lancarkan dengan pertanyaan bayang (shadow queries). Hantar sampel trafik kecil ke kedua-dua indeks baharu dan pelaksanaan lama yang dipercayai, kemudian bandingkan set 20 teratas, susunan, jarak dan kadar kehilangan. Peningkatan kependaman tidak boleh menjadi alasan untuk negatif palsu; meninggalkan tempat berdekatan yang betul adalah kegagalan ketepatan indeks.
Contoh Jawapan yang Kukuh
"Mula-mula, saya mengehadkan skop ini kepada perolehan tempat statik, bukan pemadanan pemandu yang bergerak. Katalog tempat menyimpan koordinat tepat dan versi lokasi monotonik, kemudian memancarkan peristiwa ke indeks ruang. Bacaan tidak menyusun keseluruhan jadual mengikut ungkapan latitud-longitud. Ia menukar bulatan kepada sel yang menutupinya sepenuhnya. Saya boleh bermula dengan indeks ruang PostGIS dan memperkenalkan H3, S2 atau geohash apabila trafik global memerlukan penghalaan ruang yang eksplisit. Sel hanya menapis secara kasar; jarak geografi yang tepat menentukan kemasukan, diikuti dengan pengisihan stabil pada jarak dan ID tempat.
Sel kasar menghala ke serpihan. Sel yang padat berpecah dan sel yang kerap dibaca memperoleh replika. Sesuatu pertanyaan membaca serpihan terhad secara selari, setiap satu mengembalikan k-teratas tempatan dan pengagregat menghasilkan k-teratas global. Calon yang berlebihan mencetuskan penapisan yang lebih terpilih atau pengembangan gelang, bukan pemotongan secara senyap. Calon sel dan objek tempat disimpan dalam cache dengan versi indeks. Pemindahan membatalkan kedua-dua sel, dan versi lokasi menjadikan main semula menumpu.
Kursor mengikat koordinat, jejari, penapis, versi katalog dan jarak/ID tempat terakhir. Masa tamat serpihan bermakna hasil terdekat global tidak dapat dibuktikan, jadi API penerokaan menandakan respons sebagai separa dan menamakan sel yang hilang manakala API yang ketat akan gagal. Untuk pengesahan, jarak brute-force adalah orakel. Perbandingan rawak dan kes sempadan sel yang disasarkan, garisan tarikh, kutub, seri, pemindahan dan perubahan penghalaan membuktikan ketepatan sebelum ujian beban dan kerosakan bandar panas membuktikan 150 milisaat p99."
Kesilapan Biasa
- Menanyakan geohash tengah sahaja → bulatan yang melintasi tepi sel kehilangan jiran yang dekat → baca setiap sel yang bersilang dan sahkan jarak tepat.
- Menganggap sel jiran sebagai berada di dalam jejari → bucu sel yang jauh mungkin melebihi jejari → gunakan grid untuk calon dan jarak sfera untuk kemasukan.
- Membuat serpihan secara rawak mengikut ID tempat → setiap pertanyaan berhampiran disiarkan secara global → halakan mengikut awalan ruang yang kasar, kemudian belah atau replikasi sel panas.
- Menggunakan satu resolusi paling halus → kejituan jejari kecil menghasilkan pecahan keluar jejari besar yang meletup → gunakan beberapa tahap terkawal yang dipilih daripada pengukuran.
- Mengecam cache mengikut koordinat sahaja → jejari, kategori atau versi katalog mencemari antara satu sama lain → letakkan kontrak pertanyaan dan versi yang lengkap dalam kunci.
- Memadam sebelum menambah semasa pemindahan → kegagalan pengguna mengalih keluar tempat itu buat sementara waktu → tulis versi baharu dahulu, padamkan sel lama kemudian dan nyahduplikasi mengikut versi.
- Memanggil respons "20 terdekat" selepas masa tamat serpihan → serpihan yang hilang mungkin mengandungi hasil yang lebih dekat → tandakan data separa atau gagalkan permintaan yang ketat.
- Menguji data pusat bandar yang padat sahaja → pepijat sempadan, kutub dan rantau yang jarang kekal tersembunyi → gunakan orakel brute-force, ujian sifat dan contoh lawan geometri yang disasarkan.
Soalan dan Jawapan Susulan
Susulan 1: Mengapa tidak menggunakan PostGIS untuk keseluruhan sistem?
Ia merupakan pilihan pertama yang baik. Pangkalan data ruang sedia membekalkan calon indeks dan fungsi jarak yang betul, jadi pasukan boleh melancarkan sistem yang boleh dipercayai dengan komponen yang lebih sedikit. Perkenalkan grid diskret dan peringkat carian berasingan hanya selepas pengukuran trafik, penghalaan global, pengasingan titik panas atau kos menunjukkan bahawa topologi pangkalan data tidak mencapai sasaran. Migrasi bayang (shadow migration) mesti membandingkan set hasil yang lengkap, bukan sekadar kependaman.
Susulan 2: Bagaimanakah anda membuktikan liputan sel tidak boleh terlepas tempat di dalam bulatan?
Gunakan operasi liputan bulatan atau poligon pustaka dan bukannya meneka kiraan jiran. Liputan tersebut mungkin termasuk sel tambahan, tetapi ia mesti menyertakan setiap sel yang bersilang dengan bulatan. Jarak tepat membuang positif palsu selepas itu. Bandingkan dengan orakel imbasan penuh ke atas bulatan rawak, bucu sel, garisan tarikh dan kawasan kutub. Sebarang negatif palsu akan menyekat pelepasan keluaran.
Susulan 3: Bagaimana jika pertanyaan 50 kilometer meliputi beribu-ribu sel halus?
Beralih kepada tahap lebih kasar yang telah diprakira supaya kiraan sel kekal terhad, kemudian bergantung pada penapis yang ditolak ke bawah dan penghalusan tepat. Pengembangan gelang boleh berhenti sebaik sahaja 20 hasil wujud dan jarak minimum yang mungkin bagi setiap rantau yang belum dilawati melebihi hasil kedua puluh semasa. Jika permintaan berjejari besar masih melebihi belanjawan sumbernya, tolak permintaan itu atau jadikannya tak segerak dan bukannya mencari kurang secara senyap.
Susulan 4: Bagaimanakah ini akan berubah menjadi pemadanan pemandu berhampiran?
Masalah ini berubah secara ketara. Lokasi pemandu memerlukan penulisan dan luputan skala saat, indeks yang dipisahkan mengikut bandar atau sel, dan perlindungan daripada kemas kini yang tidak mengikut susunan serta pemandu hantu. Selepas perolehan calon, pemeringkatan memerlukan ETA, keadaan dan keadilan. Tugasan akhir memerlukan kemas kini bersyarat berversi atau pemilik tunggal untuk mengelakkan penghantaran berganda; indeks ruang yang tekal akhirnya (eventually consistent) tidak boleh menempah pemandu.
Susulan 5: Adakah status waktu operasi minit demi minit akan mencetuskan ribut pembatalan sah (invalidation storm)?
Asingkan calon ruang statik daripada status dinamik. Cache sel memegang ID, lokasi dan kategori. Nod pertanyaan menilai peraturan operasi untuk open_at, manakala penutupan sementara datang daripada tindanan segar yang kecil. Hanya perubahan lokasi atau kategori yang membatalkan kesahan cache calon ruang. Pantau kesegaran tindanan dan kembalikan status tidak diketahui atau penurunan taraf yang diluluskan oleh perniagaan apabila ia tidak tersedia.