MemoryStoreService adalah layanan data dengan throughput tinggi dan latensi rendah yang menyediakan penyimpanan data dalam memori yang cepat dan dapat diakses dari semua server dalam sesi langsung. Penyimpanan Memori cocok untuk data yang sering dan sementara yang berubah dengan cepat dan tidak perlu tahan lama, karena lebih cepat diakses dan menghilang saat mencapai masa hidup 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 cepat: peta terurut, antrian, dan peta hash. Setiap struktur data cocok untuk kasus penggunaan tertentu:
- Pencocokan berbasis keterampilan - Simpan informasi pengguna, seperti tingkat keterampilan, dalam antrian bersama di antara server, dan gunakan server lobi untuk menjalankan pencocokan secara berkala.
- Perdagangan dan lelang antar server - Aktifkan perdagangan universal antara server yang berbeda, di mana pengguna dapat menawar barang dengan harga yang berubah secara real-time, dengan peta terurut dari pasangan kunci-nilai.
- Papan peringkat global - Simpan dan perbarui peringkat pengguna di papan peringkat bersama di dalam peta terurut.
- Inventaris bersama - Simpan item inventaris dan statistik dalam peta hash bersama, di mana pengguna dapat menggunakan item inventaris secara bersamaan satu sama lain.
- 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 permainan Anda.
Secara umum, jika Anda perlu mengakses data berdasarkan kunci tertentu, gunakan peta hash. Jika Anda perlu data tersebut diurutkan, gunakan peta terurut. Jika Anda perlu memproses data Anda dalam urutan tertentu, gunakan antrian.
Batasan 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 akan diusir 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 permainan. Ini bukan nilai tetap; sebaliknya, ini berubah seiring waktu tergantung pada jumlah pengguna dalam permainan sesuai dengan rumus 64 KB + 1,2 KB * [jumlah pengguna]. Kuota diterapkan pada tingkat permainan, bukan pada tingkat server.
Ketika pengguna bergabung dengan permainan, kuota memori tambahan tersedia segera. Ketika pengguna meninggalkan permainan, kuota tidak langsung berkurang. Ada periode penelusuran selama delapan hari sebelum kuota dievaluasi ulang menjadi nilai yang lebih rendah.
Setelah permainan 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 permainan Anda secara real-time menggunakan grafik Penggunaan Memori.
Batasan 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 satu unit 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 pada tingkat permainan, bukan pada tingkat server. Ini memberikan fleksibilitas untuk mengalokasikan permintaan di antara server selama total laju permintaan tidak melebihi kuota. Jika Anda melebihi kuota, Anda akan menerima respons kesalahan ketika layanan membatasi permintaan Anda.
Dengan fitur observabilitas yang tersedia, Anda dapat melihat kuota unit permintaan permainan Anda secara real-time.
Batasan 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
Batasan per-partisi
Lihat batasan per-partisi.
Praktik terbaik
Untuk menjaga pola penggunaan memori Anda tetap optimal dan menghindari mencapai batasan, 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.
Tetapkan waktu kedaluwarsa ke rentang waktu terkecil yang mungkin saat menambahkan data. Meskipun waktu kedaluwarsa default adalah 45 hari untuk baik MemoryStoreQueue:AddAsync() maupun MemoryStoreSortedMap:SetAsync(), menetapkan waktu terpendek yang mungkin dapat secara otomatis membersihkan data lama untuk mencegahnya mengisi kuota penggunaan memori Anda.
- Jangan menyimpan sejumlah besar data dengan waktu kedaluwarsa yang lama, karena berisiko melebihi kuota memori Anda dan berpotensi menyebabkan masalah yang dapat merusak seluruh permainan Anda.
- Selalu baiknya menghapus item yang tidak diperlukan secara eksplisit atau menetapkan waktu kedaluwarsa item yang pendek.
- Umumnya, Anda harus menggunakan penghapusan eksplisit untuk membebaskan memori dan waktu kedaluwarsa item sebagai mekanisme pengaman untuk mencegah item yang tidak terpakai mengisi memori dalam jangka waktu yang lama.
Hanya simpan nilai yang diperlukan dalam memori.
Misalnya, untuk permainan 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 lagi 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 sharding.
Seringkali lebih mudah untuk mengelola data dalam struktur yang lebih kecil daripada menyimpan semuanya dalam satu struktur data besar. Pendekatan ini juga dapat membantu menghindari batasan penggunaan dan laju. Misalnya, jika Anda memiliki peta terurut yang menggunakan awalan untuk kuncinya, pertimbangkan untuk memisahkan setiap awalan ke dalam peta terurutnya sendiri. Untuk permainan yang sangat populer, Anda bahkan mungkin memisahkan pengguna ke dalam beberapa peta berdasarkan digit terakhir dari ID pengguna mereka.
Shard kunci yang sering diakses 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 Ekstensi.
Anda dapat meningkatkan kuota Penyimpanan dan Permintaan Anda dengan mendaftar ke Layanan Ekstensi.
Observabilitas
Dasbor Observabilitas memberikan wawasan dan analitik untuk memantau dan memecahkan masalah penggunaan penyimpanan memori Anda. Dengan grafik yang diperbarui secara real-time tentang berbagai aspek penggunaan memori dan permintaan API Anda, Anda dapat melacak pola penggunaan memori permainan 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 Dasbor Observabilitas. Untuk informasi lebih lanjut tentang cara menyelesaikan kesalahan ini, lihat Pemecahan Masalah. Untuk kuota atau batasan spesifik yang terkait dengan kesalahan, lihat Batasan dan Kuota.
| Kode status | Deskripsi |
|---|---|
| Berhasil | Berhasil. |
| DataStructureMemoryOverLimit | Melebihi batas ukuran memori tingkat struktur data (100 MB). |
| DataUpdateConflict | Konflik karena pembaruan bersamaan. |
| AccessDenied | Tidak berwenang untuk mengakses data permainan. Permintaan ini tidak mengkonsumsi unit permintaan atau menggunakan kuota. |
| InternalError | Kesalahan internal. |
| InvalidRequest | Permintaan tidak memiliki informasi yang diperlukan atau memiliki informasi yang salah format. |
| DataStructureItemsOverLimit | Melebihi batas jumlah item tingkat struktur data (1M). |
| NoItemFound | Tidak ada item yang ditemukan di MemoryStoreQueue:ReadAsync() atau MemoryStoreSortedMap:UpdateAsync(). ReadAsync() memeriksa setiap 2 detik dan mengembalikan kode status ini sampai menemukan item di antrian. |
| 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 semesta. |
| TotalMemoryOverLimit | Melebihi kuota memori tingkat semesta. |
| ItemValueSizeTooLarge | Ukuran nilai melebihi batas (32 KB). |
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 'expiration' 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 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 |
Contoh Membatalkan Permintaan |
| 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 batasan dan kuota yang sama seperti produksi. Untuk kuota yang dihitung berdasarkan jumlah pengguna, kuota yang dihasilkan bisa sangat kecil karena Anda adalah satu-satunya pengguna untuk pengujian Studio. Saat menguji dari Studio, Anda mungkin juga memperhatikan latensi yang sedikit lebih tinggi dan tingkat kesalahan yang meningkat dibandingkan dengan penggunaan di produksi karena beberapa pemeriksaan tambahan yang dilakukan untuk memverifikasi akses dan izin.
Untuk informasi tentang cara melakukan debug penyimpanan memori di permainan langsung atau saat menguji di studio, gunakan Konsol Pengembang.