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 à partir de tous les serveurs dans une session en direct.Les magasins de mémoire sont appropriés pour les données fréquentes et éphémères qui changent rapidement et n'ont pas besoin d'être durables, car ils sont plus rapides à accéder et disparaissent lorsqu'ils atteignent la durée de vie maximale.Pour les données qui doivent persister à travers les sessions, utilisez stores de données.
Structures de données
Au lieu d'accéder directement aux données brutes, les magasins de mémoire ont trois structures de données primitives partagées sur les serveurs pour un traitement rapide : carte triée , file d'attente et carte de hachage .Chaque structure de données est une bonne option pour certains cas d'utilisation :
- Matchmaking basé sur les compétences - Enregistrer les informations utilisateur, telles que le niveau de compétence, dans une file d'attente partagée entre les serveurs, et utiliser les serveurs de lobby pour exécuter la période de matchmaking périodiquement.
- Échange et enchères interserveurs - Activer le trading universel entre différents serveurs, où les utilisateurs peuvent enchérir sur des articles avec des prix changeants en temps réel, avec une carte triée par valeur clé de paires clé-valeur.
- Classements mondiaux - Stocker et mettre à jour les classements des utilisateurs sur un classement partagé à l'intérieur d'une carte triée .
- Inventaires partagés - Sauvegarder les articles d'inventaire et les statistiques dans une carte de hachage partagée, où les utilisateurs peuvent utiliser les articles 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 mémoire en tant que carte de hachage qui peut agir comme un cache et améliorer les performances de votre expérience.
En général, si vous devez accéder à des données en fonction d'une clé spécifique, utilisez une carte de hachage.Si vous avez besoin que ces données soient commandé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 les performances du système, les magasins de mémoire ont des quotas d'utilisation des données pour la taille de la mémoire, les demandes d'API et la taille de la structure des données.
Les magasins de mémoire ont une politique d'expulsion basée sur le temps d'expiration, également appelé temps de vie (TTL).Les articles sont expulsés après leur expiration, et la quotité de mémoire est libérée pour les nouvelles entrées.Lorsque vous atteignez la limite de mémoire, toutes les demandes d'écriture suivantes échouent jusqu'à ce que les éléments expirent ou que vous les supprimez manuellement.
Quota de taille de mémoire
La limite de la quantité de mémoire empêche la quantité totale de mémoire que l'expérience peut consommer.Ce n'est pas une valeur fixe.Au lieu de cela, il change au fil du temps en fonction du nombre d'utilisateurs dans l'expérience selon la formule suivante : 64KB + 1KB * [number of users] .La quota s'applique au niveau de l'expérience au lieu du niveau du serveur.
Lorsque les utilisateurs rejoignent l'expérience, la quote-part de mémoire supplémentaire est disponible immédiatement.Lorsque les utilisateurs quittent l'expérience, le quota ne diminue pas immédiatement.Il y a une période de traçage de huit jours avant que le quota soit réévalué à une valeur inférieure.
Après que votre expérience ait atteint la limite de taille de mémoire, toutes les demandes d'API qui augmentent la taille de mémoire échouent toujours.Les demandes qui diminuent ou ne modifient pas la taille de la mémoire réussissent toujours.
Avec le tableau de bord observabilité, vous pouvez afficher la quotité de la mémoire de votre expérience en temps réel en utilisant le tableau utilisation de la mémoire .
Limites de requêtes API
Pour les limites de demande d'API, il y a une limite de unité de demande qui s'applique à toutes les appels MemoryStoreService.La quote-part est de 1000 + 100 * [nombre d'utilisateurs simultanés] unités de requête par minute.
La plupart des appels d'API ne consomment qu'une seule unité de requête, avec quelques exceptions :
MemoryStoreSortedMap:GetRangeAsync()
Consomme des unités en fonction du nombre d'objets retournés.Par exemple, si cette méthode renvoie 10 éléments, l'appel compte comme 10 unités de demande.Si elle renvoie une réponse vide, cela compte comme une unité de demande.
Consomme des unités en fonction du nombre d'objets retournés, tout comme MemoryStoreSortedMap:GetRangeAsync() , mais consomme une unité supplémentaire toutes les deux secondes en lisant.Spécifiez le temps de lecture maximum avec le paramètre waitTimeout.
MemoryStoreHashMap:UpdateAsync()
Consomme un minimum de deux unités.
MemoryStoreHashMap:ListItemsAsync()
Consomme [number of partitions scanned] + [items returned] unités.
La limite de demandes est également appliquée au niveau de l'expérience au lieu du niveau du serveur.Cela permet de flexibiliser l'allocation des demandes parmi les serveurs tant que le taux total de demande ne dépasse pas la quota.Si vous dépassez la quota, vous recevez une réponse d'erreur lorsque le service limite vos demandes.
Avec la fonctionnalité observabilité disponible, vous pouvez afficher le quota de demande d'expérience en temps réel.
Limites de taille de la structure de données
Pour une seule carte ou file d'attente triée, les limites de taille et de nombre d'objets suivantes s'appliquent :
- Nombre maximum d'objets : 1 000 000
- Taille maximale totale (y compris les clés pour la carte triée) : 100 Mo
Limites par partition
Voir limites par partition .
Meilleures pratiques
Pour maintenir votre modèle d'utilisation de la mémoire optimal et éviter de dépasser les limites limites, suivez ces meilleures pratiques :
Supprimer les articles 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 garder la structure de données à jour.
Définissez le temps d'expiration sur le plus petit délai possible lors de l'ajout de données.: Bien que le temps d'expiration par défaut soit de 45 jours pour les deux MemoryStoreQueue:AddAsync() et MemoryStoreSortedMap:SetAsync(), le réglage du temps le plus court possible peut nettoyer automatiquement les données anciennes pour empêcher 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 provoquer des problèmes qui peuvent briser toute votre expérience.
- Toujours soit supprimer explicitement des éléments inutiles, soit définir une expiration d'élément courte.
- En général, vous devez utiliser une suppression explicite pour libérer la mémoire et l'expiration des articles comme mécanisme de sécurité pour empêcher les articles inutilisés de libérer de la mémoire pendant une période prolongée.
Ne gardez que les valeurs nécessaires en mémoire.
Par exemple, pour une expérience de maison d'enchères, vous n'avez besoin de maintenir que l'offre la plus élevée.Vous pouvez utiliser MemoryStoreSortedMap:UpdateAsync() sur une clé pour conserver l'offre la plus élevée plutôt que de conserver toutes les offres dans votre structure de données.
Utilisez le ralentissement exponentiel pour vous aider à rester en dessous des limites de demande de l'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 demandes à MemoryStoreService pour obtenir la bonne réponse.
Diviser les structures de données géantes en plusieurs plus petites par fragmentation.
Il est souvent plus facile de gérer les données dans des structures plus petites plutôt que de tout stocker dans une seule 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 en une carte triée séparée.Pour une expérience particulièrement populaire, vous pouvez même séparer les utilisateurs en plusieurs cartes en fonction des derniers chiffres de leur ID d'utilisateur.
Comprimer les valeurs stockées.
Par exemple, envisagez d'utiliser l'algorithme LZW pour réduire la taille de la valeur stockée.
Observabilité
Le tableau de bord d'observabilité fournit des informations et des analyses pour surveiller et résoudre les problèmes d'utilisation de votre stock de mémoire.Avec des tableaux de mise à jour en temps réel sur différents aspects de l'utilisation de votre mémoire et des demandes d'API, vous pouvez suivre le modèle d'utilisation de la mémoire de votre expérience, afficher les quotas attribués actuels, surveiller l'statutde l'API et identifier les problèmes potentiels pour l'optimisation des performances.
La table suivante liste et décrit tous les codes d'état des réponses API disponibles sur les tableaux de demande par statut du tableau de bord d'observabilité Request Count by Status et Requests by API x Status .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 code | Avertissement |
---|---|
succès | Succès. |
Structure de données en dehors de la limite de mémoire | Dépasse la limite de mémoire de niveau de structure de données (100MB). |
Conflit de mise à jour des données | Conflit dû à une mise à jour simultanée. |
Accès refusé | Non autorisé à accéder aux données d'expérience. Cette demande ne consomme pas d'unités de demande ou n'utilise pas de quota. |
Erreur interne | Erreur interne. |
Demande non valide | La demande n'a pas les informations requises ou contient des informations mal formatées. |
DonnéesStructureItemsOverLimit | Dépasse la limite de nombre d'éléments de niveau de structure de données (1M). |
Aucun objet trouvé | Aucun élément trouvé dans MemoryStoreQueue:ReadAsync() ou MemoryStoreSortedMap:UpdateAsync(). ReadAsync() pollue toutes les 2 secondes et renvoie ce code d'état jusqu'à ce qu'il trouve des éléments dans la file d'attente. |
Demandes de structure de données au-delà de la limite | Dépasse la limite de demande de niveau de structure de données (100 000 unités de demande par minute). |
Requêtes de partition au-dessus de la limite | Dépasse la limite de demande de partition. |
TotalRequestes au-dessus de la limite | Dépasse la limite d'unité de demande au niveau de l'univers. |
Mémoire totale au-delà de la limite | Dépasse le quota de mémoire au niveau de l'univers. |
Taille de la valeur de l'article trop grande | La taille de valeur dépasse la limite (32KB). |
La table suivante liste les codes d'état du côté client, qui ne sont actuellement pas disponibles sur le tableau de bord d'observabilité.
Code de code | Avertissement |
---|---|
Erreur interne | Erreur interne. |
Lieu non publié | Vous devez publier cet endroit pour utiliser MemoryStoreService. |
Accès client non valide | Le service MemoryStoreService doit être appelé depuis le serveur. |
Temps d'expiration non valide | Le temps du champ 'expiration' doit être compris entre 0 et 3 888 000. |
Demande non valide | Impossible de convertir la valeur en json. |
Demande non valide | Impossible de convertir sortKey en un nombre ou une chaîne valide. |
TransformCallbackÉchoué | Échec d'invocation de la fonction de rappel de transformation. |
Demande limitée | Les demandes de récentes MemoryStores ont atteint une ou plusieurs limites. |
Mise à jour du conflit | Dépassé le nombre maximum de tentatives de récupération. |
Dépannage
La table suivante liste et décrit la solution recommandée pour chaque code de statut de réponse :
Erreur | Options de dépannage |
---|---|
DataStructureRequestsOverLimit / PartitionRequestsOverLimit |
|
TotalRequestes au-dessus de la limite | |
DonnéesStructureItemsOverLimit |
|
Structure de données en dehors de la limite de mémoire | |
Mémoire totale au-delà de la limite | |
Conflit de mise à jour des données |
Enquêtez pour voir si vous appelez efficacement MemoryStoreService pour éviter les conflits.Idéalement, vous ne devriez pas envoyer trop de demandes.: Supprimer de manière cohérente des é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 |
|
Demande non valide |
|
Taille de la valeur de l'article trop grande |
|
Tester et déboguer dans Studio
Les données dans MemoryStoreService sont isolées entre Studio et la production, donc le changement des données dans Studio n'affecte pas le comportement de la production.Cela signifie que vos appels API depuis Studio n'ont pas accès aux données de production, ce qui vous permet de tester en toute sécurité les magasins de mémoire et les nouvelles fonctionnalités avant de passer en production.
Les tests de 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 de Studio.Lors des tests depuis Studio, vous pouvez également remarquer une latence légèrement plus élevée et des taux d'erreur plus élevés en raison de quelques vérifications supplémentaires effectuées pour vérifier l'accès et les permissions.
Pour obtenir des informations sur la façon de déboguer un magasin de mémoire sur des expériences en direct ou lors du test en studio, utilisez la console du développeur.