Magasins mémoire

*Ce contenu est traduit en utilisant l'IA (Beta) et peut contenir des erreurs. Pour consulter cette page en anglais, clique ici.

MemoryStoreService est un service de données à fort débit et faible latence qui fournit un stockage de données rapide en mémoire accessible depuis tous les serveurs lors d'une session en direct. Les magasins mémoire sont adaptés aux données fréquentes et éphémères qui changent rapidement et n'ont pas besoin d'être durables, car elles sont plus rapides d'accès et disparaissent lorsqu'elles atteignent la durée de vie maximale. Pour les données qui doivent persister entre les sessions, utilisez les magasins de données.

Structures de données

Au lieu d'accéder directement à des données brutes, les magasins mémoire possèdent trois structures de données primitives partagées entre les serveurs pour un traitement rapide : carte triée, file d'attente, et carte de hachage. Chaque structure de données est bien adaptée à certains cas d'utilisation :

  • Matchmaking basé sur les compétences - Enregistrez les informations d'utilisateur, telles que le niveau de compétence, dans une file d'attente partagée entre les serveurs, et utilisez les serveurs de salle d'attente pour exécuter le matchmaking périodiquement.
  • Échange et enchères inter-serveurs - Permettez un échange universel entre différents serveurs, où les utilisateurs peuvent enchérir sur des objets avec des prix variant en temps réel, à l'aide d'une carte triée de paires clé-valeur.
  • Classements mondiaux - Stockez et mettez à jour les classements des utilisateurs dans un classement partagé à l'intérieur d'une carte triée.
  • Inventaires partagés - Enregistrez les objets d'inventaire et les statistiques dans une carte de hachage partagée, où les utilisateurs peuvent utiliser des objets d'inventaire en même temps.
  • Cache pour données persistantes - Synchronisez et copiez vos données persistantes dans un magasin de données vers une carte de hachage de magasin mémoire qui peut agir comme un cache et améliorer la performance de votre jeu.

En général, si vous avez besoin d'accéder aux données en fonction d'une clé spécifique, utilisez une carte de hachage. Si vous avez besoin que ces données soient ordonnées, utilisez une carte triée. Si vous devez traiter vos données dans un ordre spécifique, utilisez une file d'attente.

Limites et quotas

Pour maintenir l'évolutivité et la performance du système, les magasins mémoire ont des quotas d'utilisation des données pour la taille de la mémoire, les requêtes API et la taille de la structure de données.

Les magasins mémoire ont une politique d'éviction basée sur le temps d'expiration, également connu sous le nom de temps de vie (TTL). Les éléments sont évincés après leur expiration, et le quota de mémoire est libéré pour de nouvelles entrées. Lorsque vous atteignez la limite mémoire, toutes les requêtes d'écriture suivantes échouent jusqu'à ce que les éléments expirent ou que vous les supprimiez manuellement.

Quota de taille mémoire

Le quota de mémoire limite la quantité totale de mémoire qu'un jeu peut consommer. Ce n'est pas une valeur fixe ; au lieu de cela, elle change au fil du temps en fonction du nombre d'utilisateurs dans le jeu selon la formule 64 Ko + 1,2 Ko * [nombre d'utilisateurs]. Le quota s'applique au niveau du jeu plutôt qu'au niveau du serveur.

Lorsque des utilisateurs rejoignent le jeu, le quota de mémoire supplémentaire est disponible immédiatement. Lorsque des utilisateurs quittent le jeu, le quota ne diminue pas immédiatement. Il y a une période de rétroaction de huit jours avant que le quota soit réévalué à une valeur inférieure.

Après que votre jeu atteigne le quota de taille mémoire, toutes les requêtes API qui augmentent la taille de la mémoire échouent toujours. Les requêtes qui diminuent ou ne modifient pas la taille de la mémoire réussissent toujours.

Avec le tableau de bord observabilité, vous pouvez voir le quota de taille mémoire de votre jeu en temps réel à l'aide du graphique Utilisation de la mémoire.

Limites de requêtes API

Un quota de unités de requête s'applique à tous les appels API de MemoryStoreService. Ce quota est de 1000 + 120 * [nombre d'utilisateurs simultanés] unités de requête par minute.

La plupart des appels API ne consomment qu'une unité de requête, à quelques exceptions près :

  • MemoryStoreSortedMap:GetRangeAsync()

    Consomme des unités en fonction du nombre d'éléments retournés. Par exemple, si cette méthode retourne 10 éléments, l'appel compte comme 10 unités de requête. S'il retourne une réponse vide, il compte comme une unité de requête.

  • MemoryStoreQueue:ReadAsync()

    Consomme des unités en fonction du nombre d'éléments retournés, tout comme MemoryStoreSortedMap:GetRangeAsync(), mais consomme une unité supplémentaire toutes les deux secondes pendant que la lecture est en cours. Spécifiez le temps de lecture maximal avec le paramètre waitTimeout.

  • MemoryStoreHashMap:UpdateAsync()

    Consomme un minimum de deux unités.

  • MemoryStoreHashMap:ListItemsAsync()

    Consomme [nombre de partitions scannées] + [éléments retournés] unités.

Le quota de requêtes s'applique également au niveau du jeu plutôt qu'au niveau du serveur. Cela offre la flexibilité d'allouer les requêtes entre les serveurs tant que le taux de requêtes total ne dépasse pas le quota. Si vous dépassez le quota, vous recevrez une réponse d'erreur lorsque le service limitera vos requêtes.

Avec la fonction d'observabilité disponible, vous pouvez voir le quota d'unités de requête de votre jeu en temps réel.

Limites de taille de structure de données

Pour une seule carte triée ou file d'attente, les limites de taille et de nombre d'éléments suivantes s'appliquent :

  • Nombre maximum d'éléments : 1 000 000
  • Taille totale maximum (y compris les clés pour la carte triée) : 100 Mo

Limites par partition

Voir limites par partition.

Meilleures pratiques

Pour garder votre utilisation de mémoire optimale et éviter d'atteindre les limites, suivez ces meilleures pratiques :

  • Supprimez les éléments traités. Nettoyer de manière cohérente les éléments lus en utilisant la méthode MemoryStoreQueue:RemoveAsync() pour les files d'attente et MemoryStoreSortedMap:RemoveAsync() pour les cartes triées peut libérer de la mémoire et tenir la structure de données à jour.

  • Réglez le temps d'expiration au plus petit intervalle de temps possible lors de l'ajout de données. Bien que le temps d'expiration par défaut soit de 45 jours pour MemoryStoreQueue:AddAsync() et MemoryStoreSortedMap:SetAsync(), définir le temps le plus court possible peut nettoyer automatiquement les anciennes données pour éviter qu'elles ne remplissent votre quota d'utilisation mémoire.

    • Ne stockez pas une grande quantité de données avec un long expiration, car cela risque de dépasser votre quota mémoire et de causer potentiellement des problèmes qui peuvent casser votre jeu entier.
    • Supprimez toujours les éléments non nécessaires ou définissez une courte expiration des éléments.
    • En général, vous devriez utiliser la suppression explicite pour libérer de la mémoire et l'expiration des éléments comme un mécanisme de sécurité pour éviter que des éléments inutilisés n'occupent la mémoire pendant une longue période.
  • Ne gardez en mémoire que les valeurs nécessaires.

    Par exemple, pour un jeu de maison de vente aux enchères, vous devez seulement maintenir la plus haute enchère. Vous pouvez utiliser MemoryStoreSortedMap:UpdateAsync() sur une clé pour garder la plus haute enchère plutôt que de conserver toutes les enchères dans votre structure de données.

  • Utilisez un rétrogradage exponentiel pour rester en dessous des limites de requêtes API.

    Par exemple, si vous recevez un DataUpdateConflict, vous pourriez réessayer après deux secondes, puis quatre, huit, etc. plutôt que d'envoyer constamment des requêtes à MemoryStoreService pour obtenir la réponse correcte.

  • Séparez les grandes structures de données en plusieurs plus petites par sharding.

    Il est souvent plus facile de gérer des données dans des structures plus petites plutôt que de tout stocker dans une grande structure de données. Cette approche peut également aider à éviter les limites d'utilisation et de taux. Par exemple, si vous avez une carte triée qui utilise des préfixes pour ses clés, envisagez de séparer chaque préfixe dans sa propre carte triée. Pour un jeu particulièrement populaire, vous pourriez même séparer les utilisateurs en plusieurs cartes basées sur les derniers chiffres de leurs identifiants d'utilisateur.

  • Shard les clés fréquemment accédées dans des cartes de hachage avec plusieurs copies de la clé pour répartir la charge.

  • Compressez les valeurs stockées.

    Par exemple, envisagez d'utiliser l'algorithme LZW pour réduire la taille des valeurs stockées.

  • Inscrivez-vous aux services étendus.

    Vous pouvez augmenter vos quotas de stock et de limites de requêtes en vous inscrivant sur les services étendus.

Observabilité

Le tableau de bord d'observabilité fournit des insights et des analyses pour surveiller et dépanner votre utilisation du magasin mémoire. Avec des graphiques se mettant à jour en temps réel sur différents aspects de votre utilisation de mémoire et des requêtes API, vous pouvez suivre le modèle d'utilisation de mémoire de votre jeu, visualiser les quotas alloués actuels, surveiller l'état de l'API, et identifier les problèmes potentiels pour l'optimisation des performances.

Le tableau suivant répertorie et décrit tous les codes de statut des réponses API disponibles sur les graphiques Nombre de demandes par statut et Demandes par API x Statut du tableau de bord d'observabilité. Pour plus d'informations sur la façon de résoudre ces erreurs, voir Dépannage. Pour le quota ou la limite spécifique à laquelle une erreur se rapporte, voir Limites et Quotas.

Code de statutDescription
SuccèsSuccès.
DataStructureMemoryOverLimitDépasse la limite de taille mémoire de niveau de structure de données (100 Mo).
DataUpdateConflictConflit dû à une mise à jour concurrente.
AccessDeniedNon autorisé à accéder aux données du jeu. Cette demande ne consomme pas d'unités de requêtes ni n'utilise de quota.
InternalErrorErreur interne.
InvalidRequestLa demande ne contient pas les informations requises ou comporte des informations mal formées.
DataStructureItemsOverLimitDépasse la limite de nombre d'éléments de niveau de structure de données (1 M).
NoItemFoundAucun élément trouvé dans MemoryStoreQueue:ReadAsync() ou MemoryStoreSortedMap:UpdateAsync(). ReadAsync() interroge toutes les 2 secondes et retourne ce code de statut jusqu'à ce qu'il trouve des éléments dans la file d'attente.
DataStructureRequestsOverLimitDépasse la limite d'unités de requête de niveau de structure de données (100 000 unités de requête par minute).
PartitionRequestsOverLimitDépasse la limite d'unités de requête par partition.
TotalRequestsOverLimitDépasse la limite d'unités de requête de niveau univers.
TotalMemoryOverLimitDépasse le quota de mémoire de niveau univers.
ItemValueSizeTooLargeLa taille de la valeur dépasse la limite (32 Ko).

Le tableau suivant répertorie les codes d'état du côté client, qui ne sont actuellement pas disponibles sur le tableau de bord d'observabilité.

Code de statutDescription
InternalErrorErreur interne.
UnpublishedPlaceVous devez publier cet endroit pour utiliser MemoryStoreService.
InvalidClientAccessMemoryStoreService doit être appelé depuis le serveur.
InvalidExpirationTimeLe champ 'expiration' doit être compris entre 0 et 3 888 000.
InvalidRequestImpossible de convertir la valeur en json.
InvalidRequestImpossible de convertir sortKey en un nombre ou une chaîne valide.
TransformCallbackFailedÉchec de l'invocation de la fonction de rappel de transformation.
RequestThrottledDes requêtes récentes de MemoryStores ont atteint une ou plusieurs limites.
UpdateConflictNombre maximal de tentatives dépassé.

Dépannage

Le tableau suivant répertorie et décrit la solution recommandée pour chaque code de statut de réponse :

ErreurOptions de dépannage
DataStructureRequestsOverLimit / PartitionRequestsOverLimit
  • Ajoutez un cache local en enregistrant des informations dans une autre variable et en vérifiant à nouveau après un certain intervalle de temps, comme 30 secondes.
  • Utilisez le graphique Nombre de demandes par statut pour vérifier que vous recevez plus de réponses Succès que de Aucun élément trouvé. Limitez le nombre de fois que vous frapper MemoryStoreService avec une requête échouée.
  • Implémentez un court délai entre les requêtes.
  • Suivez les meilleures pratiques, y compris :
    • Fragmenter vos structures de données si vous recevez un nombre significatif de réponses DataStructureRequestsOverLimit/PartitionRequestsOverLimit.
    • Fragmenter vos clés de carte de hachage si vous recevez un nombre significatif de réponses PartitionRequestsOverLimit sur les appels de carte de hachage.
    • Réduire ou regrouper les appels à des structures de données spécifiques ou clés de carte de hachage si vous voyez des réponses PartitionRequestsOverLimit.
    • Implémentez un rétrogradage exponentiel pour trouver un taux raisonnable de requêtes à envoyer.
TotalRequestsOverLimit
DataStructureItemsOverLimit
DataStructureMemoryOverLimit
TotalMemoryOverLimit
DataUpdateConflict
  • Implémentez un court délai entre les requêtes pour éviter plusieurs requêtes mettant à jour la même clé en même temps.
  • Pour les cartes triées, utilisez la fonction de rappel sur la méthode MemoryStoreSortedMap:UpdateAsync() pour annuler une requête après un certain nombre d'essais, comme le montre l'exemple de code suivant :
  • Exemple d'annulation de requête

    local MemoryStoreService = game:GetService("MemoryStoreService")
    local map = MemoryStoreService:GetSortedMap("AuctionItems")
    function placeBid(itemKey, bidAmount)
    map:UpdateAsync(itemKey, function(item)
    item = item or { highestBid = 0 }
    if item.highestBid < bidAmount then
    item.highestBid = bidAmount
    return item
    end
    print("l'élément est "..item.highestBid)
    return nil
    end, 1000)
    end
    placeBid("MonObjet", 50)
    placeBid("MonObjet", 40)
    print("terminé")
  • Enquêtez pour voir si vous appelez MemoryStoreService efficacement pour éviter les conflits. Idéalement, vous ne devriez pas envoyer trop de requêtes.
  • Supprimez systématiquement les éléments une fois qu'ils ont été lus en utilisant la méthode MemoryStoreQueue:RemoveAsync() pour les files d'attente et MemoryStoreSortedMap:RemoveAsync() pour les cartes triées.
Erreur interne
InvalidRequest
  • Assurez-vous d'inclure des paramètres corrects et valides dans votre demande. Les exemples de paramètres invalides comprennent :
    • Une chaîne vide
    • Une chaîne qui dépasse la limite de longueur
ItemValueSizeTooLarge
  • Fragmenter ou diviser la valeur de l'élément en plusieurs clés.
    • Pour organiser des clés groupées, triez-les alphabétiquement en ajoutant un préfixe à la clé.
  • Encoder ou compresser les valeurs stockées.

Tester et déboguer dans Studio

Les données dans MemoryStoreService sont isolées entre Studio et la production, donc modifier les données dans Studio n'affecte pas le comportement en production. Cela signifie que vos appels API depuis Studio n'accèdent pas aux données de production, vous permettant de tester en toute sécurité les magasins mémoire et les nouvelles fonctionnalités avant de passer à la production.

Les tests en Studio ont les mêmes limites et quotas que la production. Pour les quotas calculés en fonction du nombre d'utilisateurs, le quota résultant peut être très faible puisque vous êtes le seul utilisateur lors des tests en Studio. Lorsque vous testez depuis Studio, vous pourriez également remarquer une latence légèrement plus élevée et des taux d'erreur accrus par rapport à l'utilisation en production en raison de certains contrôles supplémentaires effectués pour vérifier l'accès et les autorisations.

Pour des informations sur la façon de déboguer un magasin mémoire sur des jeux en direct ou lors de tests dans Studio, utilisez Console de développement.

©2026 Société Roblox. Roblox, le logo Roblox et Powering Imagination font partie de nos marques déposées aux États-Unis et dans d'autres pays.