Pamięci przechowywania

*Ta zawartość została przetłumaczona przy użyciu narzędzi AI (w wersji beta) i może zawierać błędy. Aby wyświetlić tę stronę w języku angielskim, kliknij tutaj.

MemoryStoreService to usługa danych o wysokiej przepustowości i niskim opóźnieniu, która zapewnia szybkie przechowywanie danych w pamięci dostępne z wszystkich serwerów w aktywnej sesji. Pamięci przechowywania są odpowiednie dla częstych i efemerycznych danych, które zmieniają się szybko i nie muszą być trwałe, ponieważ są szybsze do uzyskania dostępu i znikają po osiągnięciu maksymalnego czasu życia. Do danych, które muszą być przechowywane przez sesje, użyj przechowywań danych.

Struktury danych

Zamiast bezpośrednio uzyskiwać dostęp do surowych danych, pamięci przechowywania mają trzy podstawowe struktury danych współdzielone między serwerami dla szybkiego przetwarzania: posortowana mapa, kolejka i mapa haszowa. Każda struktura danych jest dobrze dopasowana do określonych przypadków użycia:

  • Dopasowywanie bazujące na umiejętnościach - Zapisz informacje o użytkowniku, takie jak poziom umiejętności, w współdzielonej kolejce między serwerami, i użyj serwerów lobby do okresowego uruchamiania dopasowywania.
  • Handel i aukcje międzyserwerowe - Umożliw uniwersalny handel między różnymi serwerami, gdzie użytkownicy mogą licytować przedmioty z cenami zmieniającymi się w czasie rzeczywistym, za pomocą posortowanej mapy par klucz-wartość.
  • Globalne tablice wyników - Przechowuj i aktualizuj rankingi użytkowników na współdzielonej tablicy wyników wewnątrz posortowanej mapy.
  • Wspólne ekwipunki - Zapisz przedmioty ekwipunku i statystyki w współdzielonej mapie haszowej, gdzie użytkownicy mogą równocześnie korzystać z przedmiotów ekwipunku.
  • Bufor dla danych trwałych - Synchronizuj i kopiuj swoje dane trwałe w przechowywaniu danych do pamięci mapy haszowej, która może działać jako pamięć podręczna i poprawić wydajność Twojej gry.

Ogólnie, jeśli potrzebujesz uzyskać dostęp do danych na podstawie konkretnego klucza, użyj mapy haszowej. Jeśli potrzebujesz, aby te dane były uporządkowane, użyj posortowanej mapy. Jeśli potrzebujesz przetwarzać swoje dane w określonym porządku, użyj kolejki.

Limity i kwoty

Aby utrzymać skalowalność i wydajność systemu, pamięci przechowywania mają limity użytkowania danych dla rozmiaru pamięci, żądań API i rozmiaru struktury danych.

Pamięci przechowywania mają politykę usuwania opartą na czasie wygaśnięcia, znaną również jako czas życia (TTL). Przedmioty są usuwane po upływie terminu, a limit pamięci zwalnia się na nowe wpisy. Gdy osiągniesz limit pamięci, wszystkie następne żądania zapisu zawiodą, dopóki przedmioty nie wygaśnie lub nie usuniesz ich ręcznie.

Kwota rozmiaru pamięci

Kwota pamięci ogranicza całkowitą ilość pamięci, którą gra może zużyć. To nie jest stała wartość; zamiast tego zmienia się w czasie w zależności od liczby użytkowników w grze zgodnie ze wzorem 64KB + 1.2KB * [liczba użytkowników]. Kwota ma zastosowanie na poziomie gry, a nie na poziomie serwera.

Kiedy użytkownicy dołączają do gry, dodatkowa kwota pamięci jest dostępna natychmiast. Gdy użytkownicy opuszczają grę, kwota nie zmniejsza się natychmiast. Istnieje okres przejrzystości wynoszący osiem dni, przed ponowną oceną kwoty na niższą wartość.

Po osiągnięciu przez Twoją grę kwoty rozmiaru pamięci żadne żądania API, które zwiększają rozmiar pamięci, nie powiodą się. Żądania, które zmniejszają lub nie zmieniają rozmiaru pamięci, nadal będą się powieść.

Za pomocą panelu obserwowalności możesz na bieżąco przeglądać kwotę rozmiaru pamięci swojej gry, korzystając z wykresu Zużycie pamięci.

Limity żądań API

Kwota jednostki żądania ma zastosowanie do wszystkich wywołań API MemoryStoreService. Ta kwota wynosi 1000 + 120 * [liczba jednoczesnych użytkowników] jednostek żądań na minutę.

Większość wywołań API zużywa tylko jedną jednostkę żądania, z kilkoma wyjątkami:

  • MemoryStoreSortedMap:GetRangeAsync()

    Zużywa jednostki w zależności od liczby zwróconych przedmiotów. Na przykład, jeśli ta metoda zwraca 10 przedmiotów, wywołanie liczy się jako 10 jednostek żądań. Jeśli zwraca pustą odpowiedź, liczy się jako jedna jednostka żądania.

  • MemoryStoreQueue:ReadAsync()

    Zużywa jednostki w zależności od liczby zwróconych przedmiotów, tak jak MemoryStoreSortedMap:GetRangeAsync(), ale zużywa dodatkową jednostkę co dwa sekundy podczas odczytu. Określ maksymalny czas odczytu za pomocą parametru waitTimeout.

  • MemoryStoreHashMap:UpdateAsync()

    Zużywa minimum dwie jednostki.

  • MemoryStoreHashMap:ListItemsAsync()

    Zużywa [liczba partycji skanowanych] + [przedmioty zwrócone] jednostek.

Kwota żądań jest również stosowana na poziomie gry, a nie na poziomie serwera. Zapewnia to elastyczność w przydzielaniu żądań między serwerami, pod warunkiem, że całkowita szybkość żądań nie przekracza kwoty. Jeśli przekroczysz kwotę, otrzymasz odpowiedź błędną, gdy usługa ograniczy Twoje żądania.

Dzięki funkcji obserwowalności możesz na bieżąco przeglądać kwotę jednostek żądania swojej gry.

Limity rozmiaru struktury danych

Dla pojedynczej posortowanej mapy lub kolejki obowiązują następujące limity rozmiaru i liczby przedmiotów:

  • Maksymalna liczba przedmiotów: 1,000,000
  • Maksymalny całkowity rozmiar (w tym klucze dla posortowanej mapy): 100 MB

Limity na partycje

Zobacz limity na partycje.

Najlepsze praktyki

Aby utrzymać optymalny wzór użycia pamięci i unikać przekraczania limitów, stosuj się do poniższych najlepszych praktyk:

  • Usuwaj przetworzone przedmioty. Systematyczne czyszczenie przeczytanych przedmiotów za pomocą metody MemoryStoreQueue:RemoveAsync() dla kolejek i MemoryStoreSortedMap:RemoveAsync() dla posortowanych map może zwolnić pamięć i utrzymać aktualność struktury danych.

  • Ustaw czas wygaśnięcia na jak najkrótszy, gdy dodajesz dane. Chociaż domyślny czas wygaśnięcia wynosi 45 dni zarówno dla MemoryStoreQueue:AddAsync(), jak i MemoryStoreSortedMap:SetAsync(), ustawienie jak najkrótszego czasu może automatycznie oczyścić stare dane, aby zapobiec ich zapełnianiu Twojej kwoty zużycia pamięci.

    • Nie przechowuj dużej ilości danych z długim czasem wygaśnięcia, ponieważ zagraża to przekroczeniu Twojej kwoty pamięci i potencjalnie spowoduje problemy, które mogą zrujnować całą Twoją grę.
    • Zawsze albo wyraźnie usuń niepotrzebne przedmioty, albo ustaw krótki czas wygaśnięcia przedmiotu.
    • Ogólnie rzecz biorąc, powinieneś używać wyraźnego usuwania do zwalniania pamięci, a czasu wygaśnięcia przedmiotu jako mechanizmu zabezpieczającego, aby zapobiec zapełnianiu pamięci przez nieużywane przedmioty przez długi czas.
  • Zachowuj tylko niezbędne wartości w pamięci.

    Na przykład dla gry w dom aukcyjny potrzebujesz tylko utrzymać najwyższą ofertę. Możesz użyć MemoryStoreSortedMap:UpdateAsync() na jednym kluczu, aby utrzymać najwyższą ofertę, zamiast trzymać wszystkie oferty w swojej strukturze danych.

  • Użyj ekspansyjnego opóźnienia, aby pomóc pozostać poniżej limitów żądań API.

    Na przykład, jeśli otrzymasz DataUpdateConflict, możesz spróbować ponownie po dwóch sekundach, następnie czterech, ośmiu itd. zamiast ciągłego wysyłania żądań do MemoryStoreService, aby uzyskać poprawną odpowiedź.

  • Podziel ogromne struktury danych na mniejsze za pomocą shardingu.

    Często łatwiej jest zarządzać danymi w mniejszych strukturach, niż przechowywać wszystko w jednej dużej strukturze danych. Podejście to może również pomóc uniknąć limitów użytkowania i szybkości. Na przykład, jeśli masz posortowaną mapę, która używa prefiksów dla swoich kluczy, rozważ oddzielenie każdego prefiksu do własnej posortowanej mapy. Dla szczególnie popularnej gry możesz nawet oddzielić użytkowników do wielu map na podstawie ostatnich cyfr ich identyfikatorów użytkownika.

  • Sharduj często dostępne klucze w mapach haszowych, mając kilka kopii klucza, aby rozdzielić obciążenie.

  • Kompresuj przechowywane wartości.

    Na przykład, rozważ użycie algorytmu LZW w celu zmniejszenia rozmiaru przechowywanych wartości.

  • Zapisz się do Rozszerzonych Usług.

    Możesz zwiększyć swoje limity przechowywania i żądań, przystępując do Rozszerzonych Usług.

Obserwowalność

Panel Obserwowalności zapewnia wgląd i analizy do monitorowania i rozwiązywania problemów z użyciem pamięci przechowywania. Dzięki wykresom z aktualizacjami w czasie rzeczywistym na różnych aspektach zużycia pamięci i żądań API możesz śledzić wzór zużycia pamięci swojej gry, przeglądać aktualnie przyznane kwoty, monitorować status API i identyfikować potencjalne problemy w celu optymalizacji wydajności.

Poniższa tabela zawiera listę i opis wszystkich kodów statusu odpowiedzi API dostępnych w wykresach Liczba żądań według statusu i Żądania według API x Status na panelu obserwowalności. Aby uzyskać więcej informacji na temat rozwiązywania tych błędów, zobacz Rozwiązywanie problemów. Aby uzyskać konkretny limit lub kwotę, do której odnosi się błąd, zobacz Limity i Kwoty.

Kod statusuOpis
SukcesSukces.
DataStructureMemoryOverLimitPrzekracza limit rozmiaru pamięci na poziomie struktury danych (100MB).
DataUpdateConflict Konflikt z powodu równoczesnej aktualizacji.
AccessDeniedBrak uprawnień do dostępu do danych gry. To żądanie nie zużywa jednostek żądań ani nie wykorzystuje kwoty.
InternalErrorBłąd wewnętrzny.
InvalidRequestŻądanie nie zawiera wymaganych informacji lub zawiera błędne informacje.
DataStructureItemsOverLimitPrzekracza limit liczby przedmiotów na poziomie struktury danych (1M).
NoItemFoundNie znaleziono przedmiotu w MemoryStoreQueue:ReadAsync() lub MemoryStoreSortedMap:UpdateAsync(). ReadAsync() sprawdza co 2 sekundy i zwraca ten kod statusu, aż znajdzie przedmioty w kolejce.
DataStructureRequestsOverLimitPrzekracza limit jednostek żądań na poziomie struktury danych (100,000 jednostek żądań na minutę).
PartitionRequestsOverLimitPrzekracza limit jednostek żądań na partycję.
TotalRequestsOverLimitPrzekracza limit jednostek żądań na poziomie uniwersum.
TotalMemoryOverLimitPrzekracza limit pamięci na poziomie uniwersum.
ItemValueSizeTooLargeRozmiar wartości przekracza limit (32KB).

Poniższa tabela zawiera stany kodów z strony klienta, które obecnie nie są dostępne na panelu obserwowalności.

Kod statusuOpis
InternalErrorBłąd wewnętrzny.
UnpublishedPlaceMusisz opublikować to miejsce, aby użyć MemoryStoreService.
InvalidClientAccessMemoryStoreService musi być wywoływana z serwera.
InvalidExpirationTimePole 'czas wygaśnięcia' musi być między 0 a 3,888,000.
InvalidRequestNie można przekonwertować wartości na json.
InvalidRequestNie można przekonwertować sortKey na ważną liczbę lub ciąg.
TransformCallbackFailedNie udało się wywołać funkcji zwrotnej transformacji.
RequestThrottledNiedawne żądania MemoryStores osiągnęły jedno lub więcej limitów.
UpdateConflictPrzekroczono maksymalną liczbę prób.

Rozwiązywanie problemów

Poniższa tabela zawiera listę i opis zalecanych rozwiązań dla każdego kodu statusu odpowiedzi:

BłądOpcje rozwiązywania problemów
DataStructureRequestsOverLimit / PartitionRequestsOverLimit
  • Dodaj lokalną pamięć podręczną, zapisując informacje do innej zmiennej i sprawdzając ponownie po określonym interwale czasowym, takim jak 30 sekund.
  • Użyj wykresu Liczba żądań według statusu, aby upewnić się, że otrzymujesz więcej odpowiedzi Sukces niż NoItemFounds. Ogranicz liczbę razy, kiedy wywołujesz MemoryStoreService z błędnym żądaniem.
  • Wprowadź krótkie opóźnienie między żądaniami.
  • Postępuj zgodnie z dobrymi praktykami, w tym:
    • Sharduj swoje struktury danych, jeśli otrzymujesz znacznie więcej odpowiedzi DataStructureRequestsOverLimit/PartitionRequestsOverLimit.
    • Sharduj swoje klucze mapy haszowej, jeśli otrzymujesz znaczną ilość odpowiedzi PartitionRequestsOverLimit na wywołania mapy haszowej.
    • Zmniejszaj lub hurtowo wykonuj wywołania do konkretnych struktur danych lub kluczy mapy haszowej, jeśli widzisz odpowiedzi PartitionRequestsOverLimit.
    • Wprowadź ekspansywne opóźnienie, aby znaleźć rozsądny wskaźnik żądań do wysłania.
TotalRequestsOverLimit
DataStructureItemsOverLimit
DataStructureMemoryOverLimit
TotalMemoryOverLimit
DataUpdateConflict
  • Wprowadź krótkie opóźnienie między żądaniami, aby uniknąć wielu żądań aktualizujących ten sam klucz w tym samym czasie.
  • Dla posortowanych map użyj funkcji zwrotnej w metodzie MemoryStoreSortedMap:UpdateAsync(), aby przerwać żądanie po określonej liczbie prób, jak pokazuje poniższy przykład kodu:
  • Przykład przerywania żądania

    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("przedmiot jest "..item.highestBid)
    return nil
    end, 1000)
    end
    placeBid("MyItem", 50)
    placeBid("MyItem", 40)
    print("zakończone")
  • Sprawdź, czy efektywnie wywołujesz MemoryStoreService, aby uniknąć konfliktów. Idealnie nie powinieneś nadawać żądań na wyrost.
  • Systematycznie usuwaj przedmioty po ich przeczytaniu za pomocą metody MemoryStoreQueue:RemoveAsync() dla kolejek i MemoryStoreSortedMap:RemoveAsync() dla posortowanych map.
Błąd wewnętrzny
InvalidRequest
  • Upewnij się, że zawierasz poprawne i ważne parametry w swoim żądaniu. Przykłady nieważnych parametrów obejmują:
    • Pusty ciąg
    • Ciąg, który przekracza limit długości
ItemValueSizeTooLarge
  • Sharduj lub podziel wartość przedmiotu na wiele kluczy.
    • Aby uporządkować grupowane klucze, posortuj je alfabetycznie, dodając prefiks do klucza.
  • Zakodowanie lub kompresja przechowywanych wartości.

Testowanie i debugowanie w Studio

Dane w MemoryStoreService są izolowane między Studio a produkcją, więc zmiana danych w Studio nie wpływa na zachowanie produkcji. Oznacza to, że Twoje wywołania API z Studio nie mają dostępu do danych produkcyjnych, co pozwala na bezpieczne testowanie pamięci przechowywania i nowych funkcji przed wdrożeniem do produkcji.

Testowanie w Studio ma te same limity i kwoty co produkcja. W przypadku kwot obliczanych na podstawie liczby użytkowników, wynikowa kwota może być bardzo mała, ponieważ jesteś jedynym użytkownikiem podczas testów w Studio. Podczas testowania w Studio możesz także zauważyć nieco wyższe opóźnienie i zwiększone wskaźniki błędów w porównaniu do użytkowania w produkcji z powodu dodatkowych kontroli, które są przeprowadzane, aby zweryfikować dostęp i uprawnienia.

Aby uzyskać informacje na temat tego, jak debugować pamięć przechowywania w grach na żywo lub podczas testowania w studio, użyj Konsoli dewelopera.

©2026 Roblox Corporation. Nazwa Roblox, logo Roblox oraz hasło „Powering Imagination” należą do naszych zarejestrowanych i niezarejestrowanych znaków towarowych na terenie Stanów Zjednoczonych oraz w innych krajach.