MemoryStoreService ist ein Hochdurchsatz- und latenzarmer Datenservice, der schnellen Zugriff auf Daten im Arbeitsspeicher bietet, die von allen Servern in einer Live-Sitzung zugänglich sind. Speicher für Daten sind geeignet für häufige und flüchtige Daten, die sich schnell ändern und nicht dauerhaft sein müssen, da sie schneller zugänglich sind und verschwinden, wenn die maximale Lebensdauer erreicht ist. Für Daten, die über Sitzungen hinweg bestehen bleiben müssen, verwenden Sie Datenbanken.
Datenstrukturen
Anstatt direkt auf Rohdaten zuzugreifen, verfügen Speicher für Daten über drei primitive Datenstrukturen, die serverübergreifend für eine schnelle Verarbeitung geteilt werden: sortierte Karte, Warteschlange und Hash-Karte. Jede Datenstruktur eignet sich gut für bestimmte Anwendungsfälle:
- Fähigkeitsbasiertes Matchmaking - Speichern Sie Benutzerinformationen, wie z. B. das Fähigkeitsniveau, in einer gemeinsamen Warteschlange zwischen Servern und verwenden Sie Lobby-Server, um das Matchmaking regelmäßig durchzuführen.
- Serverübergreifender Handel und Auktionen - Ermöglichen Sie universellen Handel zwischen verschiedenen Servern, bei dem Benutzer auf Artikel mit sich in Echtzeit ändernden Preisen bieten können, mit einer sortierten Karte von Schlüssel-Wert-Paaren.
- Globale Bestenlisten - Speichern und aktualisieren Sie Benutzer-Rankings auf einer gemeinsamen Bestenliste innerhalb einer sortierten Karte.
- Geteilte Inventare - Speichern Sie Inventarartikel und Statistiken in einer gemeinsamen Hash-Karte, in der Benutzer Inventarartikel gleichzeitig nutzen können.
- Cache für persistente Daten - Synchronisieren und kopieren Sie Ihre persistenten Daten in einer Datenbank in eine Hash-Karte im Speicher, die als Cache fungieren kann und die Leistung Ihres Spiels verbessert.
Im Allgemeinen, wenn Sie auf Daten basierend auf einem bestimmten Schlüssel zugreifen müssen, verwenden Sie eine Hash-Karte. Wenn Sie möchten, dass diese Daten geordnet sind, verwenden Sie eine sortierte Karte. Wenn Sie Ihre Daten in einer bestimmten Reihenfolge verarbeiten müssen, verwenden Sie eine Warteschlange.
Grenzen und Quoten
Um die Skalierbarkeit und Systemleistung aufrechtzuerhalten, haben Speicher für Daten Nutzungsquoten für die Speicherkapazität, API-Anfragen und die Größe der Datenstruktur.
Speicher für Daten haben eine Räumungspolitik basierend auf der Ablaufzeit, auch bekannt als Lebensdauer (TTL). Artikel werden nach Ablauf ihrer Frist geräumt, und der Speicherplatz wird für neue Einträge freigegeben. Wenn Sie das Speicherkontingent erreichen, schlagen alle nachfolgenden Schreibanfragen fehl, bis Artikel ablaufen oder Sie sie manuell löschen.
Speicherkapazitätsquote
Die Speicherkapazitätsquote begrenzt die gesamte Menge an Speicher, die ein Spiel verbrauchen kann. Es handelt sich nicht um einen festen Wert; stattdessen ändert er sich im Laufe der Zeit abhängig von der Anzahl der Benutzer im Spiel gemäß der Formel 64 KB + 1,2 KB * [Anzahl der Benutzer]. Die Quote gilt auf Spielebene und nicht auf Serverebene.
Wenn Benutzer dem Spiel beitreten, ist das zusätzliche Speicherkontingent sofort verfügbar. Wenn Benutzer das Spiel verlassen, wird die Quote nicht sofort reduziert. Es gibt eine Rückverfolgbarkeitsperiode von acht Tagen, bevor die Quote auf einen niedrigeren Wert neu bewertet wird.
Nachdem Ihr Spiel das Speicherkontingent erreicht hat, schlagen alle API-Anfragen, die die Speicherkapazität erhöhen, immer fehl. Anfragen, die die Speicherkapazität verringern oder nicht ändern, sind weiterhin erfolgreich.
Mit dem Beobachtungs- Dashboard können Sie die Speicherkapazitätsquote Ihres Spiels in Echtzeit mit dem Diagramm Speichernutzung anzeigen.
API-Anfragegrenzen
Eine Anfrageeinheit-Quote gilt für alle MemoryStoreService API-Aufrufe. Diese Quote beträgt 1000 + 120 * [Anzahl der gleichzeitigen Benutzer] Anfrageeinheiten pro Minute.
Die meisten API-Aufrufe verbrauchen nur eine Anfrageeinheit, mit einigen Ausnahmen:
MemoryStoreSortedMap:GetRangeAsync()
Verbraucht Einheiten basierend auf der Anzahl der zurückgegebenen Artikel. Wenn diese Methode beispielsweise 10 Artikel zurückgibt, zählt der Aufruf als 10 Anfrageeinheiten. Wenn sie eine leere Antwort zurückgibt, zählt sie als eine Anfrageeinheit.
Verbraucht Einheiten basierend auf der Anzahl der zurückgegebenen Artikel, genau wie MemoryStoreSortedMap:GetRangeAsync(), verbraucht jedoch alle zwei Sekunden eine zusätzliche Einheit während des Lesens. Geben Sie die maximale Lesezeit mit dem Parameter waitTimeout an.
MemoryStoreHashMap:UpdateAsync()
Verbraucht mindestens zwei Einheiten.
MemoryStoreHashMap:ListItemsAsync()
Verbraucht [Anzahl der gescannten Partitionen] + [zurückgegebene Artikel] Einheiten.
Die Anfragenquote gilt ebenfalls auf Spielebene und nicht auf Serverebene. Dies bietet Flexibilität, um die Anfragen unter den Servern zu verteilen, solange die gesamte Anfragequote die Quote nicht überschreitet. Wenn Sie die Quote überschreiten, erhalten Sie eine Fehlermeldung, wenn der Dienst Ihre Anfragen drosselt.
Mit der verfügbaren Beobachtungs- Funktion können Sie die Anfrageeinheitenquote Ihres Spiels in Echtzeit anzeigen.
Größenbeschränkungen der Datenstruktur
Für eine einzelne sortierte Karte oder Warteschlange gelten die folgenden Größen- und Artikelanzahlgrenzen:
- Maximale Anzahl von Artikeln: 1.000.000
- Maximale Gesamtgröße (einschließlich Schlüssel für die sortierte Karte): 100 MB
Pro-Partition-Grenzen
Siehe Pro-Partition-Grenzen.
Best Practices
Um Ihr Speicherverbrauchsmuster optimal zu halten und zu vermeiden, dass Sie die Grenzen überschreiten, befolgen Sie diese Best Practices:
Entfernen Sie verarbeitete Artikel. Durch konsequentes Bereinigen von gelesenen Artikeln mit der Methode MemoryStoreQueue:RemoveAsync() für Warteschlangen und MemoryStoreSortedMap:RemoveAsync() für sortierte Karten kann Speicherplatz freigegeben und die Datenstruktur auf dem neuesten Stand gehalten werden.
Setzen Sie die Ablaufzeit auf den kleinsten möglichen Zeitraum, wenn Sie Daten hinzufügen. Obwohl die Standardablaufzeit für sowohl MemoryStoreQueue:AddAsync() als auch MemoryStoreSortedMap:SetAsync() 45 Tage beträgt, kann das Setzen der kürzest möglichen Zeit automatisch alte Daten bereinigen, um zu verhindern, dass sie Ihr Speicherkontingent füllen.
- Speichern Sie keine große Menge an Daten mit einer langen Ablaufzeit, da dies das Risiko birgt, Ihr Speicherkontingent zu überschreiten und potenziell Probleme zu verursachen, die Ihr gesamtes Spiel beeinträchtigen können.
- Löschen Sie immer entweder explizit nicht benötigte Artikel oder setzen Sie eine kurze Artikelablaufzeit.
- Im Allgemeinen sollten Sie explizite Löschungen verwenden, um Speicher freizugeben, und die Artikelablaufzeit als Sicherheitsmechanismus, um zu verhindern, dass ungenutzte Artikel über einen längeren Zeitraum Speicher belegen.
Halten Sie nur notwendige Werte im Speicher.
Zum Beispiel, für ein Auktionshaus-Spiel müssen Sie nur das höchste Gebot aufrechterhalten. Sie können MemoryStoreSortedMap:UpdateAsync() für einen Schlüssel verwenden, um das höchste Gebot zu behalten, anstatt alle Gebote in Ihrer Datenstruktur zu speichern.
Verwenden Sie exponentielles Backoff, um unter den API-Anfragegrenzen zu bleiben.
Wenn Sie beispielsweise eine DataUpdateConflict erhalten, könnten Sie nach zwei Sekunden erneut versuchen, dann vier, acht usw., anstatt ständig Anfragen an MemoryStoreService zu senden, um die richtige Antwort zu erhalten.
Teilen Sie große Datenstrukturen in mehrere kleinere auf, indem Sie Sharding verwenden.
Es ist oft einfacher, Daten in kleineren Strukturen zu verwalten, als alles in einer großen Datenstruktur zu speichern. Dieser Ansatz kann auch helfen, Nutzungs- und Ratenlimits zu vermeiden. Wenn Sie beispielsweise eine sortierte Karte haben, die Präfixe für ihre Schlüssel verwendet, sollten Sie in Betracht ziehen, jedes Präfix in seine eigene sortierte Karte zu trennen. Für ein besonders beliebtes Spiel könnten Sie sogar Benutzer in mehrere Karten basierend auf den letzten Ziffern ihrer Benutzer-IDs aufteilen.
Shard häufig verwendete Schlüssel in Hash-Karten mit mehreren Kopien des Schlüssels, um die Last zu verteilen.
Komprimieren Sie gespeicherte Werte.
Erwägen Sie beispielsweise die Verwendung des LZW Algorithmus, um die Größe der gespeicherten Werte zu reduzieren.
Melden Sie sich für erweiterte Dienste an.
Sie können Ihre Speicher- und Anfragegrenzen erhöhen, indem Sie sich für erweiterte Dienste anmelden.
Beobachtbarkeit
Das Beobachtungs-Dashboard bietet Einblicke und Analysen zur Überwachung und Fehlersuche Ihrer Nutzung von Speicher für Daten. Mit in Echtzeit aktualisierten Diagrammen zu verschiedenen Aspekten Ihrer Speichernutzung und API-Anfragen können Sie das Muster der Speichernutzung Ihres Spiels verfolgen, die aktuellen zugewiesenen Quoten anzeigen, den API-Status überwachen und potenzielle Probleme zur Leistungsoptimierung identifizieren.
Die folgende Tabelle listet und beschreibt alle Statuscodes von API-Antworten, die auf den Diagrammen Anzahl der Anfragen nach Status und Anfragen nach API x Status des Beobachtungs-Dashboards verfügbar sind. Weitere Informationen zur Behebung dieser Fehler finden Sie unter Fehlerbehebung. Für die spezifische Quote oder Grenze, auf die sich ein Fehler bezieht, siehe Grenzen und Quoten.
| Statuscode | Beschreibung |
|---|---|
| Erfolg | Erfolg. |
| DataStructureMemoryOverLimit | Überschreitet die Speicherkapazitätsgrenze der Datenstruktur (100 MB). |
| DataUpdateConflict | Konflikt aufgrund gleichzeitiger Aktualisierung. |
| ZugriffVerweigert | Unbefugt, auf Spieldaten zuzugreifen. Diese Anfrage verbraucht keine Anfrageeinheiten oder nutzt das Kontingent. |
| InternerFehler | Interner Fehler. |
| UngültigeAnfrage | Die Anfrage enthält nicht die erforderlichen Informationen oder hat fehlerhafte Informationen. |
| DataStructureItemsOverLimit | Überschreitet die Artikelanzahlgrenze der Datenstruktur (1M). |
| KeinArtikelGefunden | Kein Artikel in MemoryStoreQueue:ReadAsync() oder MemoryStoreSortedMap:UpdateAsync() gefunden. ReadAsync() fragt alle 2 Sekunden ab und gibt diesen Statuscode zurück, bis Artikel in der Warteschlange gefunden werden. |
| DataStructureRequestsOverLimit | Überschreitet die Anfrageeinheitenobergrenze der Datenstruktur (100.000 Anfrageeinheiten pro Minute). |
| PartitionRequestsOverLimit | Überschreitet die Anfrageeinheitenobergrenze der Partition. |
| GesamtAnfragenÜberGrenze | Überschreitet die Anfrageeinheitenobergrenze auf Universumsebene. |
| GesamtSpeicherÜberGrenze | Überschreitet die Speicherkapazitätsquote auf Universumsebene. |
| ArtikelWertGrößeZuGroß | Wertgröße überschreitet die Grenze (32 KB). |
Die folgende Tabelle listet Statuscodes von der Client-Seite auf, die derzeit nicht auf dem Beobachtungs-Dashboard verfügbar sind.
| Statuscode | Beschreibung |
|---|---|
| InternerFehler | Interner Fehler. |
| UnveröffentlichtesPlatz | Sie müssen diesen Platz veröffentlichen, um MemoryStoreService zu verwenden. |
| UngültigerClientZugriff | MemoryStoreService muss vom Server aus aufgerufen werden. |
| UngültigeAblaufzeit | Das Feld 'Ablauf' muss zwischen 0 und 3.888.000 liegen. |
| UngültigeAnfrage | Wert kann nicht in JSON konvertiert werden. |
| UngültigeAnfrage | Sortierschlüssel kann nicht in eine gültige Zahl oder Zeichenfolge konvertiert werden. |
| TransformationsCallbackFehlgeschlagen | Fehler beim Aufrufen der Transformations-Callback-Funktion. |
| AnfrageDrosselt | Neueste Anfragen an MemoryStores haben eine oder mehrere Grenzen erreicht. |
| AktualisierungsKonflikt | Maximale Anzahl von Wiederholungen überschritten. |
Fehlerbehebung
Die folgende Tabelle listet und beschreibt die empfohlenen Lösungen für jeden Antwortstatuscode:
| Fehler | Fehlerbehebungsoptionen |
|---|---|
| DataStructureRequestsOverLimit / PartitionRequestsOverLimit |
|
| GesamtAnfragenÜberGrenze | |
| DataStructureItemsOverLimit |
|
| DataStructureMemoryOverLimit | |
| GesamtSpeicherÜberGrenze | |
| DataUpdateConflict |
Beispiel für das Abbrechen einer Anfrage |
| Interner Fehler |
|
| Ungültige Anfrage |
|
| ArtikelWertGrößeZuGroß |
|
Testen und Debuggen im Studio
Die Daten in MemoryStoreService sind zwischen Studio und Produktion isoliert, sodass Änderungen an den Daten im Studio das Produktionsverhalten nicht beeinflussen. Das bedeutet, dass Ihre API-Aufrufe aus dem Studio nicht auf Produktionsdaten zugreifen, was es Ihnen ermöglicht, Speicher für Daten und neue Funktionen sicher zu testen, bevor Sie in die Produktion gehen.
Das Testen im Studio hat die gleichen Grenzen und Quoten wie die Produktion. Für Quoten, die auf der Anzahl der Benutzer basieren, kann die resultierende Quote sehr klein sein, da Sie der einzige Benutzer für das Studio-Testen sind. Wenn Sie aus dem Studio testen, können Sie auch eine leicht höhere Latenz und erhöhte Fehlerquoten im Vergleich zur Nutzung in der Produktion feststellen, da einige zusätzliche Überprüfungen durchgeführt werden, um den Zugriff und die Berechtigungen zu überprüfen.
Für Informationen, wie Sie einen Speicher für Daten in Live-Spielen oder beim Testen im Studio debuggen können, verwenden Sie die Entwicklerkonsole.