Prompt dan Skop
Reka bentuk papan pendahulu bermusim untuk permainan kompetitif. Satu musim mempunyai 50 juta pemain aktif, menerima sehingga 200,000 kemas kini skor sesaat, dan menyediakan sehingga 1 juta bacaan sesaat. Pemain memerlukan 100 teratas global, kedudukan tepat mereka, dan 10 pemain di setiap sisi. Hasil yang dihantar mesti dipaparkan dalam masa 5 saat, dan bacaan p99 harus kekal di bawah 100 milisaat. Skor adalah integer dalam 0..1,000,000, dan setiap pemain hanya menyimpan skor terbaik mereka untuk musim tersebut. Pemain yang seri berkongsi kedudukan, jadi kedudukan 1, 2, 2 diikuti oleh 4. Pemain yang seri mempunyai susunan paparan yang stabil mengikut player_id, tetapi susunan tersebut tidak mengubah kedudukan mereka.
Skala, kependaman (latency) dan julat skor adalah andaian temuduga. Klien tidak boleh mengisytiharkan skor yang dipercayai. Perkhidmatan perlawanan menyelesaikan pengesahan keputusan dan pemeriksaan anti-penipuan sebelum menghasilkan peristiwa yang boleh digunakan oleh papan pendahulu. Masalah ini menguji pengindeksan teratur, pemisahan baca dan tulis, penyerpihan kunci hangat (hot-key sharding), ketekalan, kebolehbinaan semula dan kitaran hayat musim. Ia tidak meminta model anti-penipuan.
Panduan temuduga teknikal awam menyenaraikan "reka bentuk papan pendahulu untuk permainan" sebagai contoh reka bentuk sistem dan menyatakan ia menguji logik kedudukan, prestasi baca/tulis dan kemas kini masa nyata. Tutorial papan pendahulu Redis yang diterbitkan pada 2026 juga menunjukkan laluan Sorted Set asas untuk mengemas kini skor, mendapatkan semula Top-N dan mencari kedudukan. Bukti awam tidak menetapkan atribusi syarikat yang boleh dipercayai, jadi companyName kekal null.
Perkara yang Dinilai oleh Penemuduga
Isyarat pertama adalah sama ada calon mentakrifkan "kedudukan" (rank). Skor lebih tinggi dahulu adalah mudah; memutuskan sama ada seri berkongsi kedudukan, mengutamakan pencapai terawal, atau memecahkan seri mengikut ID pemain mengubah model data secara langsung. Tanpa kontrak ini, dua perkhidmatan boleh menghasilkan kedudukan yang berbeza untuk pemain yang sama.
Isyarat kedua adalah menyedari bahawa satu Sorted Set menyelesaikan satu koleksi teratur. Redis mendokumentasikan kemas kini ZADD dan carian kedudukan ZREVRANK sebagai O(log N), yang berguna untuk papan pendahulu yang sederhana. Walau bagaimanapun, Redis Cluster memperuntukkan slot hash mengikut kunci. Menyimpan papan global dalam satu kunci tidak membahagikan 50 juta ahlinya hanya kerana lebih banyak nod kluster ditambah. Jawapan yang kukuh mengekalkan laluan yang mudah terlebih dahulu, kemudian menambah penyerpihan pada peringkat aplikasi hanya apabila satu kunci melebihi belanjawan memori, tulis atau pemulihan.
Isyarat ketiga adalah menukar "tepat dalam masa 5 saat" kepada versi bacaan yang konsisten. Memindahkan pemain dari satu baldi (bucket) skor ke baldi lain mewujudkan kehilangan sementara dengan buang-kemudian-tambah, atau pendua dengan tambah-kemudian-buang. Membaca bilangan baldi dari satu ketika dan susunan baldi dari ketika yang lain juga menghasilkan kedudukan yang salah. Reka bentuk yang boleh diuji memastikan satu permintaan membaca satu versi yang diterbitkan sepenuhnya.
Akhir sekali, reka bentuk mesti boleh dikendalikan. Peristiwa skor memerlukan keidempotenan (idempotency), pembetulan mesti boleh menurunkan skor, penutupan musim mesti membekukan snapshot yang konsisten, dan cache yang hilang mesti boleh dibina semula daripada lejar yang dipercayai. Rajah yang hanya mengandungi "perkhidmatan permainan → Redis" tidak menangani pendua, titik panas (hotspots), kehilangan data, skor penipuan yang dibatalkan atau pertikaian penyelesaian.
Soalan untuk Dijelaskan Sebelum Menjawab
- Adakah skor kumulatif, terbaik atau terkini? Prompt ini mengekalkan skor terbaik bermusim. Skor kumulatif
menjadikan identiti peristiwa dan penambahan atomik penting kerana peristiwa pendua sebaliknya akan menambah dua kali. Jika adjudikator boleh membetulkan skor, API memerlukan nilai mutlak berversi dan bukan hanya ZINCRBY.
- Bagaimanakah keputusan seri diberi kedudukan? Prompt ini menggunakan kedudukan pertandingan: hanya skor yang lebih tinggi secara ketat yang dikira, dan
pemain yang seri berkongsi kedudukan. "Pencapai terawal menang" memerlukan masa pencapaian yang dipercayai dalam kunci pengisihan; susunan seri leksikografi lalai bagi ZSET tidak menyediakan peraturan tersebut secara automatik.
- Apakah keperluan ketepatan dan kesegaran? Versi yang diterbitkan mestilah tepat, dengan keusangan sehingga
5 saat. Kebolehlihatan serta-merta yang linearizable akan meletakkan penyelarasan rentas-serpihan (cross-shard) pada laluan tulis. Kedudukan anggaran akan membenarkan sampel atau lakaran kuantil (quantile sketches) dan reka bentuk yang jauh lebih mudah.
- Papan manakah yang diperlukan? Laluan utama ialah papan bermusim global. Set rantau tetap yang kecil
boleh mempunyai paparan ternyahbahan (materialized views) yang berasingan. Papan rakan biasanya mengambil skor rakan secara berkelompok dan mengisihnya bagi setiap permintaan dan bukannya mengekalkan satu papan bagi setiap pemain.
- Bacaan manakah yang disokong? 100 Teratas, kedudukan peribadi dan kejiranan 20 pemain. Penomboran halaman (pagination) yang mendalam tanpa had
mewujudkan imbasan yang mahal, jadi tetingkap harus dihadkan dan menggunakan kursor berversi. Versi yang telah tamat tempoh memerlukan penempatan semula.
- Siapakah yang mengesahkan skor? Hanya perkhidmatan keputusan perlawanan yang dipercayai menulis. Penyerahan klien ialah input
permainan, bukan skor yang boleh dimasukkan terus ke dalam indeks teratur.
- Bilakah musim ditutup? Gunakan masa peristiwa pelayan dan masa henti (cutoff) yang eksplisit. Polisi produk mesti menyatakan
sama ada keputusan lewat ditolak, disemak atau diperuntukkan di tempat lain; tugas latar belakang tidak boleh mengubah snapshot yang telah dianugerahkan secara senyap.
- Apakah yang tahan lama (durable)? Paparan kedudukan mungkin lapuk seketika atau dibina semula. Lejar skor yang dipercayai dan snapshot
musim akhir tidak boleh hilang akibat kegagalan cache.
Rangka Kerja Jawapan 30 Saat
"Saya akan mentakrifkan kedudukan sebagai 1 + bilangan pemain dengan skor yang benar-benar lebih tinggi, supaya pemain yang seri berkongsi kedudukan. Perkhidmatan perlawanan yang dipercayai menulis skor terbaik mutlak dengan event_id dan versi pemain. Jadual skor tahan lama ialah punca kebenaran (source of truth), dan strim perubahannya menzahirkan papan pendahulu. Pada skala yang lebih kecil, satu Redis Sorted Set menyokong ZADD, Top-N dan kedudukan songsang. Sebaik sahaja kunci hangat global untuk 50 juta pemain melebihi belanjawan satu serpihan, saya akan membahagikannya mengikut julat skor tetap. Kedudukan peribadi ialah bilangan dalam semua baldi yang lebih tinggi, ditambah bilangan skor yang lebih tinggi dalam baldi pemain, campur satu.
"Pergerakan rentas-baldi tidak boleh didedahkan separuh jalan. Oleh itu, penzahir (materializers) melakukan commit versi setiap beberapa saat. Selepas semua baldi, awalan bilangan (count prefixes) dan 100 Teratas sedia, penyelaras menukar manifes semasa secara atomik. Respons mengandungi leaderboard_version dan as_of. Penulisan adalah idempoten mengikut peristiwa dan versi, cache boleh dibina semula daripada lejar skor, dan penutupan musim membekukan serta menyelaraskan satu versi lengkap sebelum ganjaran dikeluarkan."
Perincian Langkah demi Langkah
Langkah 1: Tetapkan API dan kontrak susunan sebelum memilih storan.
Asingkan laluan tulis dalaman daripada bacaan awam:
POST /internal/v1/seasons/{season_id}/scores:apply
GET /v1/seasons/{season_id}/leaderboard/top?limit=100
GET /v1/seasons/{season_id}/players/{player_id}/rank
GET /v1/seasons/{season_id}/players/{player_id}/neighbors?radius=10&version=...Penulisan mengandungi event_id, match_id, player_id, mutlak best_score, score_version dan masa penyiapan yang dipercayai. Hanya identiti keputusan perlawanan dibenarkan. Bacaan mengembalikan leaderboard_version, as_of, skor, kedudukan dan ahli. Permintaan kejiranan mesti mengekalkan versi daripada respons pertama; jika tidak, perubahan kedudukan semasa penomboran halaman boleh menduplikasi atau melangkau pemain.
Empat varian kekal (invariants) memacu reka bentuk: setiap (season_id, player_id) berlaku sekali dalam satu versi; skor pemain yang diterbitkan sepadan dengan indeks teratur; kedudukan sentiasa sama dengan 1 + count(score > my_score); dan manifes hanya merujuk versi serpihan yang semuanya telah selesai.
Langkah 2: Jadikan jadual skor yang dipercayai sebagai punca kebenaran.
Perkhidmatan penyelesaian perlawanan mengesahkan kebenaran, status perlawanan dan keputusan anti-penipuan sebelum menulis lejar keputusan yang tidak boleh diubah (immutable). Dalam satu transaksi pangkalan data, penulis papan pendahulu menyahduplikasi event_id dan mengemas kini baris pemain secara bersyarat. Ia menolak versi yang lebih lama, mengembalikan hasil terdahulu untuk percubaan semula yang sama, dan menukar skor terbaik biasa hanya apabila new_score > best_score. Membatalkan skor penipuan menulis score_version yang lebih tinggi dan nilai mutlak yang dibetulkan, supaya pengurangan juga menumpu (converge).
Selepas commit, outbox atau strim perubahan tahan lama yang setara memancarkan:
ScoreChanged {
season_id, player_id, old_score, new_score,
score_version, event_id, committed_at
}Peristiwa dipisahkan mengikut pemain, dan penzahir hanya menggunakan perubahan yang lebih baharu daripada versi semasa pemain tersebut. Penghantaran pendua tidak boleh menambah mata dua kali, dan peristiwa lama yang lewat tidak boleh menimpa skor baharu. Papan pendahulu ialah paparan ternyahbahan yang boleh dilupuskan. Lejar dan jadual skor semasa ialah punca bina semula.
Langkah 3: Bentangkan reka bentuk satu-Sorted-Set terlebih dahulu.
Apabila keahlian, puncak penulisan, memori dan masa pemulihan muat dalam satu serpihan, satu ZSET setiap musim ialah titik permulaan yang betul:
key = leaderboard:{season_id}
member = player_id
score = best_scoreZADD menetapkan skor baharu untuk ahli sedia ada dan meletakkannya semula. Julat menurun mengembalikan Top-N, dan ZREVRANK mengembalikan kedudukan. Redis mendokumentasikan kemas kini sebagai O(log N), julat bersaiz tetap sebagai O(log N + M), dan carian kedudukan sebagai O(log N). Julat integer prompt 0..1,000,000 adalah jauh di bawah sempadan 2^53 di mana double mewakili integer secara tepat.
Ahli dengan skor yang sama disusun mengikut susunan leksikografi binari nilai ahli. Itu hanya sesuai dengan kontrak di mana keputusan seri berkongsi kedudukan dan ID mengawal susunan paparan. Jangan bungkus skor sewenang-wenangnya dan cap masa milisaat ke dalam satu nilai titik terapung (floating-point) dan menganggap susunan komposit kekal betul. ZREVRANK + 1 juga bukan kedudukan perniagaan yang dikongsi kerana ahli yang seri menerima kedudukan yang berbeza. Formula perniagaan ialah 1 + count(score > my_score). Di dalam satu ZSET, ZCOUNT key (my_score +inf mengira bilangan tersebut; ( menjadikan batas bawah eksklusif. Asingkan kedudukan paparan daripada kedudukan perniagaan.
Langkah 4: Buktikan mengapa skala yang lebih besar memerlukan penyerpihan peringkat aplikasi.
Redis Cluster memetakan kunci ke slot hash, dan slot yang stabil dikendalikan oleh satu nod primer. Kunci leaderboard:{season} kekal sebagai satu kunci, jadi ahlinya, penulisan dan beban pemulihan kekal tertumpu pada primer satu slot. Penyerpihan mengikut hash(player_id) mengimbangi penulisan tetapi menjadikan kedudukan global mahal kerana setiap permintaan mesti bergabung atau mengira merentas semua serpihan pemain.
Prompt ini mempunyai julat skor terhingga, jadi baldi julat skor tetap adalah berguna. Dengan satu julat 10,000 mata setiap baldi, terdapat 101 baldi:
bucket_id = floor(score / 10,000)
rank(player) = 1
+ count(all buckets with a higher bucket_id)
+ count(score > player_score inside the player's bucket)Setiap baldi kekal teratur, dan kunci baldi boleh menduduki slot yang berbeza. Bagi setiap versi, simpan bilangan baldi dan hasil tambah awalan tinggi-ke-rendah. Kedudukan peribadi kemudiannya memerlukan carian pemain, satu nilai awalan dan satu bilangan skor yang lebih tinggi secara ketat di dalam baldi tersebut. 100 Teratas hanya mengimbas baldi tidak kosong tertinggi dan dizahirkan secara berasingan. Julat tetap boleh mewujudkan baldi skor tinggi yang panas. Pecahkan julat itu lagi apabila diukur, tetapi letakkan sempadan dalam manifes berversi supaya pembaca dan penulis menggunakan susun atur yang sama.
Langkah 5: Gunakan penerbitan berversi untuk menyelesaikan keatomikan rentas-baldi.
Apabila pemain berpindah dari 39,000 ke 51,000, sistem membuang mereka dari baldi 3, menambah mereka ke baldi 5, dan menukar dua bilangan. Perubahan buang, tambah dan pembilang merentas slot Redis bukanlah satu operasi atomik biasa. Mendedahkan keadaan perantaraan menghasilkan pendua, kehilangan atau kedudukan global yang tersasar satu nombor (off-by-one).
Oleh itu, penzahir melakukan commit snapshot logik dalam epok pendek. Setiap serpihan kedudukan bermula daripada versi diterbitkan semasa, menggunakan kelompok idempoten, dan menyediakan indeks teratur dan bilangan seterusnya. Sebaik sahaja setiap serpihan melaporkan penyiapan, penyelaras menyemak jumlah keahlian, bilangan perubahan dan checksum serpihan, kemudian menukar current_manifest secara atomik daripada v kepada v+1. Bacaan mendapatkan manifes dahulu dan membawa versi tersebut melalui semua sub-pertanyaan. Versi yang belum selesai tidak dapat dilihat, serpihan yang gagal boleh mencuba semula, dan versi terdahulu kekal sehingga bacaan dalam proses selesai.
Snapshot logik boleh menggunakan semula data lama melalui MVCC, halaman salin-semasa-tulis (copy-on-write), atau asas ditambah delta, mengelakkan salinan penuh 50 juta ahli setiap beberapa saat sambil mengekalkan versi luaran yang tidak boleh diubah. Tempoh epok, lat masa pelaksanaan (apply lag), dan lat masa penerbitan mesti kekal di bawah 5 saat bersama-sama. Jika tidak, laporkan keusangan dan berhenti mendakwa perkhidmatan masa nyata dan bukannya menerbitkan versi separuh siap.
Langkah 6: Asingkan papan global, serantau dan rakan.
Papan global menggunakan indeks berbaldi. Set rantau tetap yang kecil boleh mengekalkan paparan (season, region) bebas daripada peristiwa skor yang sama. Rantau berasal daripada profil pemain yang dikekalkan oleh pelayan supaya klien tidak boleh menukar rantau semasa permintaan. Menapis Top-N global sahaja akan terlepas pemain serantau yang kuat di luar halaman global; gunakan indeks serantau atau labelkan hasilnya sebagai anggaran.
Papan rakan biasanya kecil. Ambil ID rakan berversi daripada graf sosial, baca skor mereka secara berkelompok pada versi papan pendahulu yang sama, kemudian susun mengikut score DESC, player_id ASC dan kira seri dalam perkhidmatan aplikasi. Mengekalkan satu ZSET rakan bagi setiap pemain menyebabkan penggandaan tulis (write amplification) yang melampau: satu perubahan skor merebak ke setiap papan rakan, dan perubahan perhubungan memerlukan pengisian semula (backfills).
Langkah 7: Anggarkan trafik, kemudian saizkan serpihan daripada pengukuran.
Jika satu peristiwa skor tahan lama termasuk sampulnya (envelope) ialah 128 bait, batas bawah penulisan logik puncak ialah:
200,000 events/s × 128 bytes = 25.6 MB/s
25.6 MB/s × 86,400 s = 2.21184 TB/day
three-replica log lower bound = 6.63552 TB/dayBatas bawah yang tidak dimampatkan ini tidak termasuk indeks, overhed protokol, kelompok, percubaan semula dan pemulihan replika. Hanya peristiwa yang meningkatkan skor terbaik atau membetulkannya mengubah kedudukan, tetapi setiap peristiwa yang dipercayai masih memerlukan penyahduplikasian dan audit di bahagian lejar. Satu juta bacaan sesaat tidak semuanya boleh sampai ke serpihan kedudukan. Simpan dalam cache 100 Teratas mengikut versi. Hasil peribadi boleh menggunakan TTL pendek, tetapi kuncinya termasuk pemain dan versi; serpihan kemudian membaca tetingkap kejiranan secara berkelompok.
Jangan salin bilangan serpihan tetap daripada artikel. Lakukan tanda aras (benchmark) pada memori ahli, ZADD, bilangan lebih tinggi secara ketat, bacaan julat dan pembinaan snapshot dengan 50 juta baris berbentuk pengeluaran. Rekod p50/p95/p99, CPU, memori, lat masa replikasi dan masa pemulihan, kemudian peroleh pemisahan baldi dan bilangan nod daripada penulisan puncak dan ruang kelegaan kegagalan (failure headroom). Jika satu ZSET kekal dalam setiap belanjawan, ia lebih boleh dipercayai daripada penyelaras baldi tersuai.
Langkah 8: Tutup musim dan pastikan paparan boleh dibina semula.
Selepas musim memasuki CLOSING, keputusan pra-masa henti yang telah diterima diteruskan melalui strim, manakala keputusan baharu yang tidak layak ditolak. Rekod tanda aras tinggi (high watermark) input. Sebaik sahaja setiap penzahir mencapainya, cipta versi akhir calon. Penyelesaian membandingkan jumlah pemain, jumlah bilangan baldi, 100 Teratas, kedudukan sampel rawak, bilangan pemain pendua dan setiap checksum serpihan. Jika berjaya, tandakan manifes FINAL; perkhidmatan ganjaran hanya membaca versi yang tidak boleh diubah itu. Pertikaian kemudiannya memasuki aliran pembetulan yang diaudit dan bukannya menulis semula papan yang telah dianugerahkan secara senyap.
Jika cache kedudukan atau keseluruhan kluster hilang, mainkan semula jadual skor semasa atau lejar yang tidak boleh diubah mengikut score_version ke dalam ruang nama baharu. Bina dan selaraskan calon yang lengkap, kemudian tukar manifes secara atomik. Versi lama kekal baca sahaja semasa bina semula. Jika tiada yang wujud, kembalikan status tidak tersedia buat sementara waktu yang eksplisit atau status lapuk daripada mempersembahkan papan separa sebagai lengkap.
Matriks kerosakan merangkumi peristiwa pendua dan tidak mengikut urutan; peningkatan rentas-baldi dan pembetulan menurun; kerosakan serpihan pada pertengahan epok; kerosakan penyelaras sebelum dan selepas pertukaran manifes; kehilangan nod cache; seri yang banyak pada sempadan 100 Teratas; 1 juta QPS bacaan; keputusan lewat sekitar masa henti; dan binaan semula penuh dengan perbandingan bayang (shadow comparison). Tegaskan empat varian kekal secara berterusan dan pantau p99 peristiwa-ke-terbit, umur versi, kecondongan baldi (bucket skew), peristiwa yang ditolak, kemajuan bina semula dan kegagalan checksum.
Contoh Jawapan yang Kukuh
"Saya akan mentakrifkan kedudukan terlebih dahulu. Pemain yang seri berkongsi kedudukan di sini, jadi kedudukan pemain ialah 1 + bilangan pemain dengan skor yang benar-benar
lebih tinggi; kedudukan paparan 100 Teratas dan kedudukan perniagaan adalah berasingan. Klien tidak boleh menulis skor yang dipercayai. Selepas pengesahan perlawanan, penulis papan pendahulu menyahduplikasi ID peristiwa dan menetapkan skor terbaik mutlak secara bersyarat mengikut versi skor pemain. Jadual skor semasa ialah punca kebenaran, dan strim perubahannya yang telah di-commit memacu paparan kedudukan.
"Jika papan itu muat dalam satu serpihan Redis, saya akan bermula dengan satu Sorted Set setiap musim. Menetapkan skor, membaca Top-N dan mengira mengikut skor adalah secara langsung. Tetapi papan global untuk 50 juta pemain ialah satu kunci hangat, dan Redis Cluster menyerpih mengikut kunci dan bukannya mengikut ahli dalam kunci. Memandangkan julat skor dihadkan pada 0..1,000,000, saya akan meningkatkan skala kepada 101 baldi julat skor tetap. Kedudukan peribadi ialah awalan bilangan baldi yang lebih tinggi ditambah pemain yang lebih tinggi secara ketat dalam baldi tempatan campur satu. 100 Teratas datang daripada baldi tidak kosong yang tertinggi.
"Pergerakan rentas-baldi mengubah dua kunci dan bilangan. Mengemas kini di tempat (in place) akan mendedahkan keadaan perantaraan, jadi saya akan membina indeks seterusnya dalam epok paling lama beberapa saat. Hanya selepas setiap serpihan menggunakan perubahan idempoten dan penyelarasan keahlian/checksum lulus, barulah penyelaras menukar manifes semasa secara atomik. Setiap respons termasuk versi dan as-of, dan bacaan kejiranan mengekalkan versi tersebut. Versi yang diterbitkan adalah tepat dengan kos keusangan sehingga 5 saat.
"Pada 128 bait setiap peristiwa, penulisan puncak ialah 25.6 MB/s trafik logik, kira-kira 2.21 TB sehari, dan batas bawah log tiga replika ialah kira-kira 6.64 TB. Nod indeks dan bilangan baldi masih diperoleh daripada tanda aras pada data berbentuk pengeluaran. Simpan 100 Teratas dalam cache mengikut versi. Bina papan rakan dengan mengambil skor rakan secara berkelompok dan mengisih secara tempatan, mengelakkan perebakan (fan-out) pada setiap perubahan skor.
"Pada penutupan musim, saya akan merekodkan tanda aras tinggi input, menunggu semua serpihan mengejar, dan membekukan versi akhir calon. Saya akan menyelaraskan keahlian, jumlah baldi, 100 Teratas, kedudukan sampel dan checksum serpihan sebelum perkhidmatan ganjaran membaca manifes FINAL. Cache yang hilang dibina semula daripada jadual skor atau lejar yang dipercayai. Ujian kerosakan meliputi peristiwa pendua/tidak teratur, pembetulan rentas-baldi, kerosakan serpihan dan penyelaras, seri yang berat, perlumbaan masa henti dan binaan semula penuh."
Kesilapan Biasa
- Menerima skor terus daripada klien → stor susunan tidak dapat menentukan sama ada ia sah → hanya gunakan keputusan yang diaudit dan disahkan oleh perkhidmatan perlawanan yang dipercayai.
- Gunakan
ZREVRANK + 1untuk kedudukan seri → ZSET memberikan skor yang sama kedudukan leksikografi yang berbeza, melanggar kontrak kedudukan berkongsi → kira1 + count(score > my_score). - Membungkus cap masa secara santai ke dalam skor titik terapung → double mempunyai batas kejituan dan pengekodan komposit boleh membalikkan keutamaan kunci → takrifkan seri dahulu, kemudian gunakan pengekodan integer yang terbukti atau indeks susunan komposit.
- Menganggap lebih banyak nod Redis Cluster memisahkan satu kunci papan global → Kluster memperuntukkan slot hash kunci, dan kunci tunggal kekal pada satu primer slot → ukur sempadan kunci tunggal, kemudian serpihkan mengikut dimensi perniagaan yang boleh digabungkan.
- Menyerpihkan pemain secara hash dan menyebarkan (fan out) setiap pertanyaan kedudukan → kos pertanyaan berkembang dengan bilangan serpihan dan meletup pada 1 juta QPS bacaan → gunakan bilangan ke atas julat skor terhingga, atau kembalikan kedudukan anggaran jika dibenarkan.
- Membuang kemudian menambah, atau menambah kemudian membuang, merentas baldi → pembaca melihat kehilangan, pendua atau bilangan yang salah → bina versi lengkap dan terbitkannya secara atomik melalui manifes.
- Gunakan
ZINCRBYuntuk setiap keputusan → peristiwa pendua menambah dua kali dan pembatalan skor penipuan tidak boleh berkurang dengan selamat → tetapkan skor mutlak secara idempoten mengikut peristiwa dan versi pemain. - Mengeluarkan ganjaran daripada cache langsung pada masa henti → peristiwa pra-masa henti yang diterima mungkin masih dalam proses, dan cache bukan kebenaran tahan lama → rekod tanda aras tinggi, kejar, selaraskan dan bekukan versi FINAL.
- Mengesahkan hanya bahawa 100 Teratas kelihatan betul → ralat bilangan baldi atau pemain yang diduplikasi boleh mengalihkan setiap kedudukan ekor panjang (long-tail) → sahkan pemuliharaan keahlian, keunikan, formula kedudukan sampel, checksum serpihan dan binaan semula penuh.
Soalan Susulan dan Maklum Balas
Susulan 1: Bolehkah kita mengekalkan snapshot lima saat jika pemain mesti membaca apa yang ditulis serta-merta?
Asingkan pengalaman baca-apa-yang-anda-tulis (read-your-writes) penulis daripada kedudukan yang diterbitkan secara global. Respons penulisan boleh mengembalikan skor baharu yang telah di-commit dan versi yang belum selesai. Muat semula serta-merta boleh menyatakan bahawa skor telah disahkan dan kedudukan global sedang dikemas kini, atau menunjukkan skor peribadi baharu sementara kedudukan global masih merujuk manifes lengkap terkini. Jika produk memerlukan skor baharu dan kedudukan global yang tepat dalam respons segerak yang sama, kemas kini mesti memasuki laluan susunan yang diselaraskan secara global. Kependaman tulis dan gandingan kegagalan (failure coupling) meningkat, jadi sasaran daya pemprosesan asal mesti dinilai semula.
Susulan 2: Bagaimana jika 10 juta pemain terkumpul dalam baldi skor tertinggi?
Susun atur baldi ialah metadata berversi. Mula-mula buktikan titik panas melalui QPS tulis, keahlian, CPU dan p99, kemudian bahagikan julat skor itu kepada sub-baldi yang lebih sempit. Oleh kerana kedudukan berkongsi bergantung pada skor yang lebih tinggi secara ketat, satu skor tepat tidak boleh diserpihkan mengikut pemain sewenang-wenangnya dan kedudukan tempatan dijumlahkan; jumlah bilangannya mesti kekal diagregatkan. Bina susun atur baharu secara selari, bandingkan keahlian dan kedudukan sampel pada tanda aras tinggi input yang sama, dan kemudian terbitkan manifes yang merujuk susun atur baharu tersebut.
Susulan 3: Apakah yang berubah jika pemain terawal yang mencapai skor seri menang?
Kedudukan bukan lagi bilangan berasaskan skor sahaja. Kunci pengisihan menjadi (score DESC, achieved_at ASC, player_id ASC), dengan achieved_at datang daripada penyelesaian yang dipercayai. ZSET biasa hanya menyelesaikan seri mengikut susunan leksikografi ahli. Skor integer lebar tetap dan pengekodan ahli songsang boleh berfungsi apabila kejituan dan susunannya terbukti, tetapi ia rapuh. Pada skala yang lebih besar, saya lebih suka serpihan teratur yang menyokong kunci komposit dan statistik susunan, dengan ujian untuk milisaat yang sama, percubaan semula dan masa pencapaian yang dibetulkan.
Susulan 4: Apakah yang berlaku jika anti-penipuan membatalkan juara selepas ganjaran dikeluarkan?
Sistem teknikal tidak boleh memutuskan sama ada ganjaran ditarik balik. Ia menerima pembetulan negatif dengan score_version yang lebih tinggi, mengekalkan peristiwa asal, bukti, pelulus dan masa, serta menghasilkan manifes baharu yang dibetulkan tanpa menulis semula snapshot FINAL yang asal. Perkhidmatan ganjaran menggunakan dasar operasi untuk membekukan, memulihkan atau menaikkan pangkat ganjaran dan mengaitkan tindakannya dengan versi papan pendahulu. Ini mengekalkan penjelasan untuk kedua-dua anugerah asal dan pembetulan kemudian.
Susulan 5: Bagaimanakah anda membuktikan binaan semula lejar sepadan dengan papan pendahulu dalam talian?
Mainkan semula versi peristiwa ke tanda aras tinggi input yang sama dalam ruang nama yang diasingkan. Bandingkan bilangan pemain, bilangan mengikut baldi skor, jumlah skor dan hash, 100 Teratas, banyak sampel pemain berstrata menggunakan 1 + count(higher score), dan checksum deterministik untuk setiap serpihan. Buat perbandingan bayang (shadow) pada kedua-dua laluan baca dan kira sebarang perbezaan skor, kedudukan atau tetingkap jiran. Tukar manifes hanya selepas setiap ambang lulus. Tugas bina semula yang keluar dengan jayanya bukanlah bukti bahawa hasilnya adalah betul.