Magasins de 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 à haut débit et faible latence qui fournit un stockage de données en mémoire rapide accessible depuis tous les serveurs dans une session en direct. Les magasins de 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 ils sont plus rapides d'accès et disparaissent lorsqu'ils 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 aux données brutes, les magasins de mémoire disposent de 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 :

  • Appariement basé sur les compétences - Enregistrez les informations des utilisateurs, telles que le niveau de compétence, dans une file d'attente partagée entre les serveurs, et utilisez des serveurs de lobby pour exécuter l'appariement périodiquement.
  • Échanges 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 changeant en temps réel, avec une carte triée de paires clé-valeur.
  • Classements mondiaux - Stockez et mettez à jour les classements des utilisateurs sur 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 les objets d'inventaire simultanément les uns avec les autres.
  • Cache pour les données persistantes - Synchronisez et copiez vos données persistantes dans un magasin de données vers une carte de hachage de magasin de mémoire qui peut agir comme un cache et améliorer les performances de votre jeu.

En général, si vous devez 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 la scalabilité et la performance du système, les magasins de 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 de 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 de 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 de 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 retour de huit jours avant que le quota ne soit réévalué à une valeur inférieure.

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

Avec le tableau de bord d'observabilité, vous pouvez voir le quota de taille de 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é 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, avec quelques exceptions :

  • 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, cela 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 la lecture. Spécifiez le temps de lecture maximum 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 une flexibilité pour répartir les requêtes entre les serveurs tant que le taux total de requêtes ne dépasse pas le quota. Si vous dépassez le quota, vous recevez une réponse d'erreur lorsque le service limite vos requêtes.

Avec la fonctionnalité 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 maximale (y compris les clés pour la carte triée) : 100 Mo

Limites par partition

Voir les limites par partition.

Meilleures pratiques

Pour garder votre modèle d'utilisation de la mémoire optimal et éviter d'atteindre les limites, suivez ces meilleures pratiques :

  • Supprimez les éléments traités. Nettoyer régulièrement 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 garder la structure de données à jour.

  • Définissez le temps d'expiration au plus petit intervalle 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 automatiquement nettoyer les anciennes données pour éviter qu'elles ne remplissent votre quota d'utilisation de mémoire.

    • Ne stockez pas une grande quantité de données avec une longue expiration, car cela risque de dépasser votre quota de mémoire et de potentiellement causer des problèmes qui peuvent casser votre jeu entier.
    • Supprimez toujours explicitement les éléments non nécessaires ou définissez une courte expiration pour les é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 empêcher les éléments inutilisés d'occuper de la mémoire pendant une période prolongée.
  • Ne gardez que les valeurs nécessaires en mémoire.

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

  • Utilisez un retour exponentiel pour aider à 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 bonne réponse.

  • Divisez les grandes structures de données en plusieurs plus petites en shardant.

    Il est souvent plus facile de gérer les 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 en fonction des derniers chiffres de leurs identifiants d'utilisateur.

  • Shard les clés fréquemment accédées dans les 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 Limite de Stockage et de Requête en vous inscrivant aux Services Étendus.

Observabilité

Le Tableau de bord d'Observabilité fournit des informations et des analyses pour surveiller et dépanner votre utilisation des magasins de mémoire. Avec des graphiques se mettant à jour en temps réel sur différents aspects de votre utilisation de la mémoire et des requêtes API, vous pouvez suivre le modèle d'utilisation de la mémoire de votre jeu, voir 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 d'état des réponses API disponibles sur les graphiques Nombre de requêtes par statut et Requêtes 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 d'étatDescription
SuccèsSuccès.
DataStructureMemoryOverLimitDépasse la limite de taille de mémoire au niveau de la structure de données (100 Mo).
DataUpdateConflictConflit dû à une mise à jour concurrente.
AccessDeniedNon autorisé à accéder aux données du jeu. Cette requête ne consomme pas d'unités de requête ni n'utilise de quota.
InternalErrorErreur interne.
InvalidRequestLa requête n'a pas les informations requises ou a des informations mal formées.
DataStructureItemsOverLimitDépasse la limite de nombre d'éléments au niveau de la structure de données (1M).
NoItemFoundAucun élément trouvé dans MemoryStoreQueue:ReadAsync() ou MemoryStoreSortedMap:UpdateAsync(). ReadAsync() interroge toutes les 2 secondes et retourne ce code d'état jusqu'à ce qu'il trouve des éléments dans la file d'attente.
DataStructureRequestsOverLimitDépasse la limite d'unités de requête au niveau de la structure de données (100 000 unités de requête par minute).
PartitionRequestsOverLimitDépasse la limite d'unités de requête de partition.
TotalRequestsOverLimitDépasse la limite d'unités de requête au niveau de l'univers.
TotalMemoryOverLimitDépasse le quota de mémoire au niveau de l'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 d'étatDescription
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.
RequestThrottledLes requêtes récentes de MemoryStores ont atteint une ou plusieurs limites.
UpdateConflictDépassement du nombre maximum de tentatives.

Dépannage

Le tableau suivant répertorie et décrit la solution recommandée pour chaque code d'état 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 requêtes 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 où vous frappez MemoryStoreService avec une requête échouée.
  • Implémentez un court délai entre les requêtes.
  • Suivez les meilleures pratiques, y compris :
    • Shard vos structures de données si vous recevez un nombre significatif de réponses DataStructureRequestsOverLimit/PartitionRequestsOverLimit.
    • Shard 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éduisez ou regroupez les appels à des structures de données spécifiques ou des clés de carte de hachage si vous voyez des réponses PartitionRequestsOverLimit.
    • Implémentez un retour 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 que plusieurs requêtes ne mettent à 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 de tentatives, 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("MyItem", 50)
    placeBid("MyItem", 40)
    print("terminé")
  • Enquêtez pour voir si vous appelez MemoryStoreService de manière efficace 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 sont 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 requête. Des exemples de paramètres invalides incluent :
    • Une chaîne vide
    • Une chaîne qui dépasse la limite de longueur
ItemValueSizeTooLarge
  • Shard ou divisez la valeur de l'élément en plusieurs clés.
    • Pour organiser les clés groupées, triez-les par ordre alphabétique en ajoutant un préfixe à la clé.
  • Encodage ou compression des valeurs stockées.

Tester et déboguer dans Studio

Les données dans MemoryStoreService sont isolées entre Studio et la production, donc changer les données dans Studio n'affecte pas le comportement de 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 de 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 pour les 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 certaines vérifications supplémentaires effectuées pour vérifier l'accès et les autorisations.

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

©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.