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 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 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, permintaan yang meningkatkan penggunaan memori gagal sampai Anda membebaskan memori atau meningkatkan kuota Anda. Lihat Pulihkan dari kehabisan kuota memori untuk opsi.
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 pelacakan 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, batasan 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
Selain kuota unit permintaan tingkat permainan, penyimpanan memori menerapkan batasan permintaan pada setiap partisi sebagai langkah pengaman yang melindungi stabilitas layanan untuk semua permainan. Batasan ini bukan kuota yang dialokasikan untuk permainan Anda, dan bukan batas keras pada throughput yang dapat dicapai permainan Anda. Nilai berikut adalah perkiraan. Mereka dikonfigurasi di backend Roblox dan dapat berubah, jadi jangan merancang berdasarkan angka tetap.
Setiap permintaan dihitung terhadap batasan partisi yang menyimpan item, terlepas dari struktur data. Anda saat ini dapat mengharapkan pembatasan mulai pada sekitar 30.000 unit permintaan per menit untuk satu partisi, jadi usahakan untuk tetap jauh di bawah laju itu. Seberapa banyak batasan itu dikonsumsi oleh struktur data tergantung pada bagaimana itemnya didistribusikan:
- Peta terurut dan antrian masing-masing berada di satu partisi, jadi setiap permintaan ke salah satu struktur data ini dihitung terhadap batasan partisi yang sama.
- Peta hash menyebarkan itemnya di banyak partisi, jadi lalu lintas yang tersebar di banyak kunci item jarang mendekati batasan salah satu partisi.
Peta hash memiliki batasan tambahan pada setiap kunci item sekitar 5.000 unit permintaan tulis per menit dan 15.000 unit permintaan baca per menit. Batasan per-kunci ini berlaku di atas batasan per-partisi, jadi kunci yang sering diakses dapat mencapai salah satu dari keduanya. Batasan per-kunci hanya berlaku untuk operasi satu kunci: batasan baca berlaku untuk MemoryStoreHashMap:GetAsync(), batasan tulis berlaku untuk MemoryStoreHashMap:SetAsync() dan MemoryStoreHashMap:RemoveAsync(), dan MemoryStoreHashMap:UpdateAsync() dihitung terhadap batasan baca dan tulis. MemoryStoreHashMap:ListItemsAsync() memindai partisi daripada satu kunci, jadi hanya batasan per-partisi yang berlaku untuknya.

Jika Anda tidak memerlukan pengurutan atau fungsi first-in, first-out, peta hash biasanya adalah pilihan terbaik karena dapat menyebarkan beban di antara partisi.
Ketika permintaan melebihi batasan partisi atau per-kunci, layanan membatasi mereka dan mengembalikan kode status PartitionRequestsOverLimit, yang dapat Anda pantau dengan dasbor observabilitas.
Jika Anda mengharapkan struktur data atau kunci item menerima laju permintaan yang tinggi dan berkelanjutan, shard sehingga beban tersebar di lebih banyak partisi atau kunci. Sebarkan baca dan tulis secara merata di antara beberapa kunci item untuk tetap berada dalam batasan per-kunci. Anda juga dapat mengurangi laju permintaan dengan menyimpan nilai di server dan memeriksanya kembali setelah interval, mengelompokkan permintaan jika memungkinkan, dan menerapkan exponential backoff ketika Anda menerima respons pembatasan.
Pulihkan dari kehabisan kuota memori
Jika permainan Anda menerima kesalahan TotalMemoryOverLimit, periksa grafik Penggunaan Memori di dasbor observabilitas. Untuk melanjutkan penulisan yang meningkatkan penggunaan memori, hapus item yang tidak diperlukan, tunggu item kedaluwarsa, atau gunakan salah satu opsi berikut.
Kosongkan penyimpanan memori dengan Open Cloud
Jika Anda tidak lagi memerlukan data yang disimpan, gunakan endpoint Open Cloud Flush Memory Store untuk secara asinkron menghapus semua struktur data penyimpanan memori dalam satu alam semesta untuk ruang lingkup yang dipilih.
Untuk mengosongkan penyimpanan memori:
- Buat kunci API dengan izin untuk mengosongkan penyimpanan memori dan mendapatkan status operasi pengosongan untuk alam semesta target.
- Kirim permintaan POST ke https://apis.roblox.com/cloud/v2/universes/{universe_id}/memory-store:flush dengan kunci API di header x-api-key. Ganti {universe_id} dengan ID alam semesta permainan Anda. Atur parameter kueri scope ke LIVE untuk data produksi atau TEST untuk data Studio. Jika Anda mengabaikan scope, endpoint menggunakan LIVE.
- Gunakan Get Memory Store Flush Operation untuk memantau operasi yang dikembalikan oleh permintaan pengosongan hingga done adalah true, dan periksa apakah ada error. Gunakan ruang lingkup yang sama saat memantau. Jalur yang dikembalikan sudah termasuk cloud/v2, jadi pantau di https://apis.roblox.com/{path} tanpa menambahkan awalan lain.
Penyimpanan memori Studio dan produksi diisolasi. Mengosongkan satu ruang lingkup tidak menghapus yang lain. Setelah menghapus data yang tidak diperlukan, ikuti praktik terbaik, seperti waktu kedaluwarsa yang lebih pendek dan penghapusan eksplisit, untuk mencegah penggunaan memori mencapai kuota lagi.
Tingkatkan kapasitas dengan Layanan Ekstensi
Jika permainan Anda perlu mempertahankan data dan menggunakan lebih banyak penyimpanan daripada kuota default yang diizinkan, aktifkan Layanan Ekstensi untuk penyimpanan memori. Layanan Ekstensi memungkinkan Anda membayar untuk penyimpanan dan permintaan penyimpanan memori di luar kuota default.
Untuk memulai, penuhi persyaratan kelayakan, tambahkan detail akun dan metode pembayaran, lalu pilih permainan Anda di Dasbor Pembuat. Di bawah Layanan Ekstensi, aktifkan penyimpanan memori dan atur anggaran bulanan untuk sumber daya yang Anda butuhkan. Lihat Aktifkan layanan dan Harga layanan untuk detail.
Layanan Ekstensi membatasi layanan jika penggunaan melebihi anggaran Anda. Pantau penggunaan dan penagihan, dan terus hapus data yang tidak diperlukan.
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 mutakhir.
Atur waktu kedaluwarsa ke rentang waktu terkecil yang mungkin saat menambahkan data. Meskipun waktu kedaluwarsa default adalah 45 hari untuk baik MemoryStoreQueue:AddAsync() dan MemoryStoreSortedMap:SetAsync(), mengatur 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 mengatur waktu kedaluwarsa item yang pendek.
- Secara umum, Anda harus menggunakan penghapusan eksplisit untuk membebaskan memori dan waktu kedaluwarsa item sebagai mekanisme pengaman untuk mencegah item yang tidak terpakai mengisi memori untuk 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 exponential backoff untuk membantu tetap di bawah batasan permintaan API.
Misalnya, jika Anda menerima DataUpdateConflict, Anda mungkin mencoba lagi setelah dua detik, lalu 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 di Layanan Ekstensi.
Untuk penggunaan penyimpanan atau permintaan di luar kuota default, aktifkan Layanan Ekstensi untuk penyimpanan memori.
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 | Melampaui 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 | Melampaui batas jumlah item tingkat struktur data (1M). |
| NoItemFound | Tidak ada item yang ditemukan di MemoryStoreQueue:ReadAsync() atau MemoryStoreSortedMap:UpdateAsync(). ReadAsync() memindai setiap 2 detik dan mengembalikan kode status ini sampai menemukan item di antrian. |
| DataStructureRequestsOverLimit | Melampaui batas unit permintaan tingkat struktur data (100.000 unit permintaan per menit). |
| PartitionRequestsOverLimit | Melampaui batas unit permintaan per-partisi atau per-kunci. |
| TotalRequestsOverLimit | Melampaui batas unit permintaan tingkat alam semesta. |
| TotalMemoryOverLimit | Melampaui kuota memori tingkat alam 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 '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 batasan. |
| UpdateConflict | Melampaui 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 dapat 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.