MemoryStoreService adalah layanan data dengan throughput tinggi dan latensi rendah yang menyediakan penyimpanan data memori cepat yang dapat diakses dari semua server dalam sesi yang aktif. Penyimpanan Memori cocok untuk data yang sering dan sementara yang berubah dengan cepat dan tidak perlu bersifat tahan lama, karena lebih cepat diakses dan menghilang saat mencapai umur maksimum. Untuk data yang perlu bertahan di antara sesi, gunakan data store.
Struktur data
Alih-alih mengakses data mentah secara langsung, penyimpanan memori memiliki tiga struktur data primitif yang dibagikan di seluruh server untuk pemrosesan yang cepat: peta terurut, antrian, dan peta hash. Setiap struktur data cocok untuk kasus penggunaan tertentu:
- Pemilihan berdasarkan keterampilan - Simpan informasi pengguna, seperti tingkat keterampilan, dalam antrian yang dibagikan di antara server, dan gunakan server lobi untuk menjalankan pemilihan secara berkala.
- Perdagangan dan pelelangan antar server - Mengizinkan perdagangan universal antara berbagai server, di mana pengguna dapat menawar item dengan harga yang berubah secara real-time, dengan peta terurut pasangan kunci-nilai.
- Papan peringkat global - Simpan dan perbarui peringkat pengguna di papan peringkat yang dibagikan di dalam peta terurut.
- Inventaris bersama - Simpan item inventaris dan statistik dalam peta hash yang dibagikan, di mana pengguna dapat memanfaatkan item inventaris secara bersamaan.
- Cache untuk Data Persisten - Sinkronkan dan salin data persisten Anda di data store ke peta hash penyimpanan memori yang dapat bertindak sebagai cache dan meningkatkan kinerja game Anda.
Secara umum, jika Anda perlu mengakses data berdasarkan kunci tertentu, gunakan peta hash. Jika Anda membutuhkan data tersebut diurutkan, gunakan peta terurut. Jika Anda perlu memproses data Anda dalam urutan tertentu, gunakan antrian.
Batas dan kuota
Untuk mempertahankan skalabilitas dan kinerja sistem, penyimpanan memori memiliki kuota penggunaan data untuk ukuran memori, permintaan API, dan ukuran struktur data.
Penyimpanan memori memiliki kebijakan pengusiran berdasarkan waktu kedaluwarsa, juga dikenal sebagai waktu hidup (TTL). Item dikeluarkan setelah kedaluwarsa, dan kuota memori dibebaskan untuk entri baru. Ketika Anda mencapai batas memori, semua permintaan tulis berikutnya gagal sampai item kedaluwarsa atau Anda menghapusnya secara manual.
Kuota ukuran memori
Kuota memori membatasi total jumlah memori yang dapat digunakan oleh sebuah game. Ini bukan nilai tetap; sebaliknya, berubah seiring waktu tergantung pada jumlah pengguna dalam game sesuai dengan rumus 64KB + 1.2KB * [jumlah pengguna]. Kuota diterapkan di level game, bukan di level server.
Ketika pengguna bergabung dengan game, kuota memori tambahan tersedia segera. Ketika pengguna meninggalkan game, kuota tidak langsung berkurang. Ada periode penelusuran selama delapan hari sebelum kuota dievaluasi ulang ke nilai yang lebih rendah.
Setelah game Anda mencapai kuota ukuran memori, permintaan API yang meningkatkan ukuran memori selalu gagal. Permintaan yang mengurangi atau tidak mengubah ukuran memori tetap berhasil.
Dengan dasbor observabilitas, Anda dapat melihat kuota ukuran memori game Anda secara real-time menggunakan grafik Penggunaan Memori.
Batas permintaan API
Kuota unit permintaan berlaku untuk semua panggilan API MemoryStoreService. Kuota ini adalah 1000 + 120 * [jumlah pengguna bersamaan] unit permintaan per menit.
Sebagian besar panggilan API hanya mengkonsumsi satu unit permintaan, dengan beberapa pengecualian:
MemoryStoreSortedMap:GetRangeAsync()
Mengkonsumsi unit berdasarkan jumlah item yang dikembalikan. Misalnya, jika metode ini mengembalikan 10 item, panggilan dihitung sebagai 10 unit permintaan. Jika mengembalikan respons kosong, dihitung sebagai satu unit permintaan.
Mengkonsumsi unit berdasarkan jumlah item yang dikembalikan, sama seperti MemoryStoreSortedMap:GetRangeAsync(), tetapi mengkonsumsi tambahan setiap dua detik saat membaca. Tentukan waktu baca maksimum dengan parameter waitTimeout.
MemoryStoreHashMap:UpdateAsync()
Mengkonsumsi minimal dua unit.
MemoryStoreHashMap:ListItemsAsync()
Mengkonsumsi [jumlah partisi yang dipindai] + [item yang dikembalikan] unit.
Kuota permintaan juga diterapkan di level game, bukan di level server. Ini memberikan fleksibilitas untuk mendistribusikan permintaan di antara server selama total laju permintaan tidak melebihi kuota. Jika Anda melebihi kuota, Anda akan menerima respons kesalahan saat layanan mengurangi permintaan Anda.
Dengan fitur observabilitas yang tersedia, Anda dapat melihat kuota unit permintaan game Anda secara real time.
Batas ukuran struktur data
Untuk satu peta terurut atau antrian, batas ukuran dan jumlah item berikut berlaku:
- Jumlah maksimum item: 1.000.000
- Ukuran total maksimum (termasuk kunci untuk peta terurut): 100 MB
Batas per-partisi
Lihat batas per-partisi.
Praktik terbaik
Untuk menjaga pola penggunaan memori Anda tetap optimal dan menghindari mencapai batas, ikuti praktik terbaik berikut:
Hapus item yang telah diproses. Secara konsisten membersihkan item yang dibaca menggunakan metode MemoryStoreQueue:RemoveAsync() untuk antrian dan MemoryStoreSortedMap:RemoveAsync() untuk peta terurut dapat membebaskan memori dan menjaga struktur data tetap terkini.
Tentukan waktu kedaluwarsa ke rentang waktu terkecil yang memungkinkan saat menambahkan data. Meskipun waktu kedaluwarsa default adalah 45 hari untuk MemoryStoreQueue:AddAsync() dan MemoryStoreSortedMap:SetAsync(), menetapkan waktu terpendek dapat secara otomatis membersihkan data lama untuk mencegahnya mengisi kuota penggunaan memori Anda.
- Jangan menyimpan sejumlah besar data dengan waktu kedaluwarsa yang panjang, karena ada risiko melebihi kuota memori Anda dan berpotensi menyebabkan masalah yang dapat merusak seluruh game Anda.
- Selalu hapus item yang tidak diperlukan secara eksplisit atau tetapkan kedaluwarsa item yang pendek.
- Secara umum, Anda harus menggunakan penghapusan eksplisit untuk membebaskan memori dan kedaluwarsa item sebagai mekanisme keamanan untuk mencegah item yang tidak terpakai menghabiskan memori dalam waktu yang lama.
Hanya simpan nilai yang diperlukan dalam memori.
Misalnya, untuk game rumah lelang, Anda hanya perlu mempertahankan tawaran tertinggi. Anda dapat menggunakan MemoryStoreSortedMap:UpdateAsync() pada satu kunci untuk menjaga tawaran tertinggi daripada menyimpan semua tawaran dalam struktur data Anda.
Gunakan backoff eksponensial untuk membantu tetap di bawah batas permintaan API.
Misalnya, jika Anda menerima DataUpdateConflict, Anda mungkin mencoba kembali setelah dua detik, kemudian empat, delapan, dll. daripada terus-menerus mengirim permintaan ke MemoryStoreService untuk mendapatkan respons yang benar.
Pisahkan struktur data besar menjadi beberapa yang lebih kecil dengan penyerpihan.
Seringkali lebih mudah mengelola data dalam struktur yang lebih kecil daripada menyimpan semuanya dalam satu struktur data besar. Pendekatan ini juga dapat membantu menghindari penggunaan dan batas laju. Misalnya, jika Anda memiliki peta terurut yang menggunakan awalan untuk kuncinya, pertimbangkan untuk memisahkan masing-masing awalan menjadi peta terurutnya sendiri. Untuk game yang sangat populer, Anda bahkan dapat memisahkan pengguna ke dalam beberapa peta berdasarkan digit terakhir dari ID pengguna mereka.
Shard kunci yang diakses sering dalam peta hash dengan beberapa salinan kunci untuk mendistribusikan beban.
Kompres nilai yang disimpan.
Misalnya, pertimbangkan untuk menggunakan algoritma LZW untuk mengurangi ukuran nilai yang disimpan.
Daftar untuk Layanan yang Diperpanjang.
Anda dapat meningkatkan kuota Penyimpanan dan Permintaan Anda dengan bergabung ke Layanan yang Diperpanjang.
Observabilitas
Dasbor Observabilitas memberikan wawasan dan analisis untuk memantau dan memecahkan masalah penggunaan penyimpanan memori Anda. Dengan grafik yang diperbarui secara real-time tentang berbagai aspek penggunaan memori Anda dan permintaan API, Anda dapat melacak pola penggunaan memori game Anda, melihat kuota yang dialokasikan saat ini, memantau status API, dan mengidentifikasi masalah potensial untuk optimasi kinerja.
Tabel berikut mencantumkan dan menjelaskan semua kode status dari respons API yang tersedia di grafik Jumlah Permintaan berdasarkan Status dan Permintaan berdasarkan API x Status di Observabilitas Dashboard. Untuk informasi lebih lanjut tentang cara menyelesaikan kesalahan ini, lihat Pemecahan Masalah. Untuk kuota atau batas tertentu yang terkait dengan kesalahan, lihat Batas dan Kuota.
| Kode status | Deskripsi |
|---|---|
| Success | Berhasil. |
| DataStructureMemoryOverLimit | Melebihi batas ukuran memori tingkat struktur data (100MB). |
| DataUpdateConflict | Konflik karena pembaruan bersamaan. |
| AccessDenied | Tidak diizinkan untuk mengakses data game. Permintaan ini tidak mengkonsumsi unit permintaan atau menggunakan kuota. |
| InternalError | Kesalahan internal. |
| InvalidRequest | Permintaan tidak memiliki informasi yang diperlukan atau memiliki informasi yang tidak valid. |
| DataStructureItemsOverLimit | Melebihi batas jumlah item tingkat struktur data (1M). |
| NoItemFound | Tidak ada item yang ditemukan dalam MemoryStoreQueue:ReadAsync() atau MemoryStoreSortedMap:UpdateAsync(). ReadAsync() memindai setiap 2 detik dan mengembalikan kode status ini sampai menemukan item di antrean. |
| DataStructureRequestsOverLimit | Melebihi batas unit permintaan tingkat struktur data (100.000 unit permintaan per menit). |
| PartitionRequestsOverLimit | Melebihi batas unit permintaan partisi. |
| TotalRequestsOverLimit | Melebihi batas unit permintaan tingkat univers. |
| TotalMemoryOverLimit | Melebihi kuota memori tingkat univers. |
| ItemValueSizeTooLarge | Ukuran nilai melebihi batas (32KB). |
Tabel berikut mencantumkan kode status dari sisi klien, yang saat ini tidak tersedia di Dasbor Observabilitas.
| Kode status | Deskripsi |
|---|---|
| InternalError | Kesalahan Internal. |
| UnpublishedPlace | Anda harus menerbitkan tempat ini untuk menggunakan MemoryStoreService. |
| InvalidClientAccess | MemoryStoreService harus dipanggil dari server. |
| InvalidExpirationTime | Waktu 'kedaluwarsa' harus antara 0 dan 3.888.000. |
| InvalidRequest | Tidak dapat mengonversi nilai ke json. |
| InvalidRequest | Tidak dapat mengonversi sortKey menjadi angka atau string yang valid. |
| TransformCallbackFailed | Gagal memanggil fungsi callback transformasi. |
| RequestThrottled | Permintaan MemoryStores yang baru-baru ini mencapai satu atau lebih batas. |
| UpdateConflict | Melebihi jumlah maksimum percobaan. |
Pemecahan Masalah
Tabel berikut mencantumkan dan menjelaskan solusi yang direkomendasikan untuk setiap kode status respons:
| Kesalahan | Opsi pemecahan masalah |
|---|---|
| DataStructureRequestsOverLimit / PartitionRequestsOverLimit |
|
| TotalRequestsOverLimit | |
| DataStructureItemsOverLimit |
|
| DataStructureMemoryOverLimit | |
| TotalMemoryOverLimit | |
| DataUpdateConflict |
|
| Kesalahan Internal |
|
| InvalidRequest |
|
| ItemValueSizeTooLarge |
|
Uji dan debug di Studio
Data dalam MemoryStoreService terisolasi antara Studio dan produksi, jadi mengubah data di Studio tidak mempengaruhi perilaku produksi. Ini berarti bahwa panggilan API Anda dari Studio tidak mengakses data produksi, memungkinkan Anda untuk menguji penyimpanan memori dan fitur baru dengan aman sebelum masuk ke produksi.
Pengujian Studio memiliki batas dan kuota yang sama dengan produksi. Untuk kuota yang dihitung berdasarkan jumlah pengguna, kuota yang dihasilkan mungkin sangat kecil karena Anda adalah satu-satunya pengguna untuk pengujian Studio. Saat menguji dari Studio, Anda mungkin juga melihat latensi sedikit lebih tinggi dan tingkat kesalahan yang meningkat dibandingkan penggunaan di produksi karena beberapa pemeriksaan tambahan yang dilakukan untuk memverifikasi akses dan izin.
Untuk informasi tentang cara melakukan debug penyimpanan memori pada game live atau saat menguji di studio, gunakan Konsol Pengembang.