Armazenamentos de memória

*Este conteúdo é traduzido por IA (Beta) e pode conter erros. Para ver a página em inglês, clique aqui.

MemoryStoreService é um serviço de dados de alta capacidade e baixa latência que fornece armazenamento rápido de dados em memória acessível a partir de todos os servidores em uma sessão ao vivo. Armazenamentos de Memória são adequados para dados frequentes e efêmeros que mudam rapidamente e não precisam ser duráveis, pois são mais rápidos de acessar e desaparecem ao atingirem a vida útil máxima. Para dados que precisam persistir entre sessões, use data stores.

Estruturas de dados

Em vez de acessar dados brutos diretamente, os armazenamentos de memória têm três estruturas de dados primitivas compartilhadas entre os servidores para processamento rápido: mapa ordenado, fila e mapa hash. Cada estrutura de dados é adequada para certos casos de uso:

  • Matchmaking baseado em habilidades - Salve informações dos usuários, como nível de habilidade, em uma fila compartilhada entre servidores, e use servidores de lobby para executar o matchmaking periodicamente.
  • Comércio e leilão entre servidores - Habilite o comércio universal entre diferentes servidores, onde os usuários podem fazer lances em itens com preços que mudam em tempo real, usando um mapa ordenado de pares chave-valor.
  • Classificações globais - Armazene e atualize as classificações dos usuários em uma classificação compartilhada dentro de um mapa ordenado.
  • Inventários compartilhados - Salve itens e estatísticas de inventário em um mapa hash compartilhado, onde os usuários podem utilizar itens de inventário simultaneamente uns com os outros.
  • Cache para Dados Persistentes - Sincronize e copie seus dados persistentes em um data store para um mapa hash de armazenamento em memória que pode agir como um cache e melhorar o desempenho do seu jogo.

Em geral, se você precisa acessar dados com base em uma chave específica, use um mapa hash. Se você precisa que esses dados estejam ordenados, use um mapa ordenado. Se você precisa processar seus dados em uma ordem específica, use uma fila.

Limites e cotas

Para manter a escalabilidade e o desempenho do sistema, os armazenamentos de memória possuem cotas de uso de dados para o tamanho da memória, solicitações da API e o tamanho da estrutura de dados.

Os armazenamentos de memória têm uma política de evacuação baseada no tempo de expiração, também conhecido como tempo de vida útil (TTL). Os itens são evacuados após expirarem, e a cota de memória é liberada para novas entradas. Quando você atinge o limite de memória, todas as solicitações de gravação subsequentes falham até que os itens expirem ou que você os exclua manualmente.

Cota de tamanho da memória

A cota de memória limita a quantidade total de memória que um jogo pode consumir. Não é um valor fixo; em vez disso, muda ao longo do tempo dependendo do número de usuários no jogo de acordo com a fórmula 64KB + 1.2KB * [número de usuários]. A cota se aplica no nível do jogo em vez de no nível do servidor.

Quando os usuários entram no jogo, a cota de memória adicional está disponível imediatamente. Quando os usuários saem do jogo, a cota não é reduzida imediatamente. Há um período de retrocesso de oito dias antes que a cota seja reavaliada para um valor mais baixo.

Depois que seu jogo atinge a cota de tamanho de memória, qualquer solicitação da API que aumente o tamanho da memória sempre falha. Solicitações que diminuem ou não alteram o tamanho da memória ainda têm sucesso.

Com o painel de observabilidade, você pode visualizar a cota de tamanho da memória do seu jogo em tempo real usando o gráfico de Uso da Memória.

Limites de solicitações da API

Uma cota de unidade de solicitação se aplica a todas as chamadas da API MemoryStoreService. Essa cota é 1000 + 120 * [número de usuários concorrentes] unidades de solicitação por minuto.

A maioria das chamadas da API consome apenas uma unidade de solicitação, com algumas exceções:

  • MemoryStoreSortedMap:GetRangeAsync()

    Consome unidades com base no número de itens retornados. Por exemplo, se este método retornar 10 itens, a chamada conta como 10 unidades de solicitação. Se retornar uma resposta vazia, conta como uma unidade de solicitação.

  • MemoryStoreQueue:ReadAsync()

    Consome unidades com base no número de itens retornados, assim como MemoryStoreSortedMap:GetRangeAsync(), mas consome uma unidade adicional a cada dois segundos enquanto lê. Especifique o tempo máximo de leitura com o parâmetro waitTimeout.

  • MemoryStoreHashMap:UpdateAsync()

    Consome um mínimo de duas unidades.

  • MemoryStoreHashMap:ListItemsAsync()

    Consome [número de partições escaneadas] + [itens retornados] unidades.

A cota de solicitações também se aplica no nível do jogo em vez de no nível do servidor. Isso fornece flexibilidade para alocar as solicitações entre os servidores, desde que a taxa total de solicitações não exceda a cota. Se você exceder a cota, receberá uma resposta de erro quando o serviço limitar suas solicitações.

Com o recurso de observabilidade disponível, você pode visualizar a cota da unidade de solicitação do seu jogo em tempo real.

Limites de tamanho da estrutura de dados

Para um único mapa ordenado ou fila, os seguintes limites de tamanho e contagem de itens se aplicam:

  • Número máximo de itens: 1.000.000
  • Tamanho total máximo (incluindo chaves para mapa ordenado): 100 MB

Limites por partição

Veja limites por partição.

Melhores práticas

Para manter seu padrão de uso de memória ideal e evitar atingir os limites, siga estas melhores práticas:

  • Remova itens processados. Limpar consistentemente itens lidos usando o método MemoryStoreQueue:RemoveAsync() para filas e MemoryStoreSortedMap:RemoveAsync() para mapas ordenados pode liberar memória e manter a estrutura de dados atualizada.

  • Defina o tempo de expiração para o menor intervalo de tempo possível ao adicionar dados. Embora o tempo de expiração padrão seja 45 dias para ambos MemoryStoreQueue:AddAsync() e MemoryStoreSortedMap:SetAsync(), definir o tempo mais curto possível pode automaticamente limpar dados antigos para evitar que eles preencham sua cota de uso de memória.

    • Não armazene uma grande quantidade de dados com uma longa expiração, pois isso arrisca ultrapassar sua cota de memória e potencialmente causar problemas que podem quebrar seu jogo inteiro.
    • Sempre exclua explicitamente itens desnecessários ou defina uma expiração de itens curta.
    • Geralmente, você deve usar exclusão explícita para liberar memória e expiração de itens como um mecanismo de segurança para evitar que itens não utilizados ocupem memória por um período prolongado.
  • Mantenha apenas os valores necessários na memória.

    Por exemplo, para um jogo de leilão, você só precisa manter o maior lance. Você pode usar MemoryStoreSortedMap:UpdateAsync() em uma chave para manter o maior lance em vez de manter todos os lances na sua estrutura de dados.

  • Use backoff exponencial para ajudar a permanecer abaixo dos limites de solicitações da API.

    Por exemplo, se você receber um DataUpdateConflict, você pode tentar novamente após dois segundos, depois quatro, oito, etc., em vez de continuar enviando solicitações para MemoryStoreService para obter a resposta correta.

  • Separe estruturas de dados gigantes em várias menores por meio de sharding.

    Muitas vezes é mais fácil gerenciar dados em estruturas menores do que armazenar tudo em uma grande estrutura de dados. Essa abordagem também pode ajudar a evitar limites de uso e taxa. Por exemplo, se você tiver um mapa ordenado que usa prefixos para suas chaves, considere separar cada prefixo em seu próprio mapa ordenado. Para um jogo especialmente popular, você pode até separar usuários em vários mapas com base nos últimos dígitos de seus IDs de usuário.

  • Shard chaves frequentemente acessadas em mapas hash com várias cópias da chave para distribuir a carga.

  • Comprimir valores armazenados.

    Por exemplo, considere usar o algoritmo LZW para reduzir o tamanho do valor armazenado.

  • Inscrever-se em Serviços Estendidos.

    Você pode aumentar suas cotas de Limite de Armazenamento e Solicitações ao aderir aos Serviços Estendidos.

Observabilidade

O Painel de Observabilidade fornece insights e análises para monitorar e solucionar problemas do uso do seu armazenamento de memória. Com gráficos atualizados em tempo real sobre diferentes aspectos do seu uso de memória e solicitações da API, você pode rastrear o padrão de uso de memória do seu jogo, visualizar as cotas atuais alocadas, monitorar o status da API e identificar possíveis problemas para otimização de desempenho.

A tabela a seguir lista e descreve todos os códigos de status das respostas da API disponíveis nas chartas Contagem de Solicitações por Status e Solicitações por API x Status do Painel de Observabilidade. Para mais informações sobre como resolver esses erros, veja Solução de Problemas. Para a cota ou limite específico relacionado a um erro, veja Limites e Cotas.

Código de statusDescrição
SucessoSucesso.
DataStructureMemoryOverLimitExcede o limite de tamanho da memória a nível de estrutura de dados (100MB).
DataUpdateConflictConflito devido a atualização concorrente.
AccessDeniedNão autorizado a acessar os dados do jogo. Esta solicitação não consome unidades de solicitação ou usa cota.
InternalErrorErro interno.
InvalidRequestA solicitação não contém as informações necessárias ou possui informações malformadas.
DataStructureItemsOverLimitExcede o limite de contagem de itens a nível de estrutura de dados (1M).
NoItemFoundNenhum item encontrado em MemoryStoreQueue:ReadAsync() ou MemoryStoreSortedMap:UpdateAsync(). ReadAsync() verifica a cada 2 segundos e retorna este código de status até encontrar itens na fila.
DataStructureRequestsOverLimitExcede o limite de unidades de solicitação a nível de estrutura de dados (100.000 unidades de solicitação por minuto).
PartitionRequestsOverLimitExcede o limite de unidades de solicitação por partição.
TotalRequestsOverLimitExcede o limite de unidades de solicitação a nível do universo.
TotalMemoryOverLimitExcede a cota de memória a nível do universo.
ItemValueSizeTooLargeO tamanho do valor excede o limite (32KB).

A tabela a seguir lista códigos de estado do lado do cliente, que atualmente não estão disponíveis no Painel de Observabilidade.

Código de statusDescrição
InternalErrorErro interno.
UnpublishedPlaceVocê deve publicar este lugar para usar o MemoryStoreService.
InvalidClientAccessMemoryStoreService deve ser chamado a partir do servidor.
InvalidExpirationTimeO campo 'expiração' deve estar entre 0 e 3.888.000.
InvalidRequestIncapaz de converter valor em json.
InvalidRequestIncapaz de converter sortKey em um número ou string válidos.
TransformCallbackFailedFalha ao invocar a função de retorno de chamada de transformação.
RequestThrottledRecentes solicitações de MemoryStores atingiram um ou mais limites.
UpdateConflictExcedido o número máximo de tentativas.

Solução de problemas

A tabela a seguir lista e descreve a solução recomendada para cada código de status de resposta:

ErroOpções de solução de problemas
DataStructureRequestsOverLimit / PartitionRequestsOverLimit
  • Adicione um cache local salvando informações em outra variável e verificando novamente após um determinado intervalo de tempo, como 30 segundos.
  • Use o gráfico Contagem de Solicitações por Status para verificar se você está recebendo mais respostas de Sucesso do que NoItemFounds. Limite a quantidade de vezes que você atinge MemoryStoreService com uma solicitação falhada.
  • Implemente um atraso curto entre solicitações.
  • Siga as melhores práticas, incluindo:
    • Shard suas estruturas de dados se você receber uma quantidade significativa de respostas DataStructureRequestsOverLimit/PartitionRequestsOverLimit.
    • Shard suas chaves do mapa hash se você receber uma quantidade significativa de respostas PartitionRequestsOverLimit nas chamadas do mapa hash.
    • Reduza ou agrupe chamadas a estruturas de dados específicas ou chaves de mapa hash se você ver respostas PartitionRequestsOverLimit.
    • Implemente um backoff exponencial para encontrar uma taxa razoável de solicitações a enviar.
TotalRequestsOverLimit
DataStructureItemsOverLimit
DataStructureMemoryOverLimit
TotalMemoryOverLimit
DataUpdateConflict
  • Implemente um curto atraso entre solicitações para evitar várias solicitações atualizando a mesma chave ao mesmo tempo.
  • Para mapas ordenados, use a função de retorno de chamada no método MemoryStoreSortedMap:UpdateAsync() para abortar uma solicitação após um certo número de tentativas, conforme o seguinte exemplo de código:
  • Exemplo de Abortando Solicitação

    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("item é "..item.highestBid)
    return nil
    end, 1000)
    end
    placeBid("MyItem", 50)
    placeBid("MyItem", 40)
    print("concluído")
  • Investigue para ver se você está chamando MemoryStoreService de maneira eficiente para evitar conflitos. Idealmente, você não deveria enviar solicitações em excesso.
  • Remova consistentemente itens uma vez que eles são lidos usando o método MemoryStoreQueue:RemoveAsync() para filas e MemoryStoreSortedMap:RemoveAsync() para mapas ordenados.
Erro Interno
InvalidRequest
  • Certifique-se de incluir parâmetros corretos e válidos em sua solicitação. Exemplos de parâmetros inválidos incluem:
    • Uma string vazia
    • Uma string que excede o limite de comprimento
ItemValueSizeTooLarge
  • Shard ou divida o valor do item em várias chaves.
    • Para organizar chaves agrupadas, ordene-as alfabeticamente adicionando um prefixo à chave.
  • Codificando ou comprimindo valores armazenados.

Testar e depurar no Studio

Os dados em MemoryStoreService são isolados entre o Studio e a produção, portanto, modificar os dados no Studio não afeta o comportamento em produção. Isso significa que suas chamadas de API do Studio não acessam dados de produção, permitindo que você teste com segurança os armazenamentos de memória e novos recursos antes de ir para a produção.

Os testes no Studio têm os mesmos limites e cotas que a produção. Para cotas calculadas com base no número de usuários, a cota resultante pode ser muito pequena, já que você é o único usuário para o teste no Studio. Ao testar a partir do Studio, você também pode notar uma latência ligeiramente maior e taxas de erro elevadas em comparação ao uso na produção devido a algumas verificações adicionais que são realizadas para verificar acesso e permissões.

Para obter informações sobre como depurar um armazenamento de memória em jogos ativos ou ao testar no studio, use o Console do Desenvolvedor.

©2026 Roblox Corporation, Roblox, o logotipo Roblox e Powering Imagination estão entre nossas marcas registradas e não registradas nos EUA e em outros países.