Armazenamentos em 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 de todos os servidores em uma sessão ao vivo. Armazenamentos em 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 atingir a vida útil máxima. Para dados que precisam persistir entre sessões, use armazenamentos de dados.

Estruturas de dados

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

  • Matchmaking baseado em habilidade - Salve informações do usuário, como nível de habilidade, em uma fila compartilhada entre servidores, e use servidores de lobby para executar o matchmaking periodicamente.
  • Trocas e leilões entre servidores - Permita trocas universais entre diferentes servidores, onde os usuários podem dar lances em itens com preços que mudam em tempo real, com um mapa ordenado de pares chave-valor.
  • Classificações globais - Armazene e atualize as classificações dos usuários em uma tabela de classificação compartilhada dentro de um mapa ordenado.
  • Inventários compartilhados - Salve itens de inventário e estatísticas em um mapa hash compartilhado, onde os usuários podem utilizar itens de inventário simultaneamente entre si.
  • Cache para Dados Persistentes - Sincronize e copie seus dados persistentes em um armazenamento de dados para um mapa hash de armazenamento em memória que pode atuar 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 sejam 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 em memória têm cotas de uso de dados para o tamanho da memória, solicitações de API e o tamanho da estrutura de dados.

Os armazenamentos em memória têm uma política de expulsão baseada no tempo de expiração, também conhecido como tempo de vida (TTL). Os itens são expulsos 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 você os exclua manualmente.

Cota de tamanho de 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 64 KB + 1,2 KB * [número de usuários]. A cota se aplica no nível do jogo em vez do 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 rastreamento 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, quaisquer solicitações de API que aumentem o tamanho da memória sempre falham. 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 de memória do seu jogo em tempo real usando o gráfico de Uso de Memória.

Limites de solicitações de API

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

A maioria das chamadas de 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 é aplicada no nível do jogo em vez do nível do servidor. Isso fornece flexibilidade para alocar as solicitações entre 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 de 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 otimizado 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 de 45 dias para ambos MemoryStoreQueue:AddAsync() e MemoryStoreSortedMap:SetAsync(), definir o menor tempo possível pode limpar automaticamente dados antigos para evitar que preencham sua cota de uso de memória.

    • Não armazene uma grande quantidade de dados com uma longa expiração, pois isso pode exceder 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 curta para os itens.
    • Geralmente, você deve usar a exclusão explícita para liberar memória e a expiração de itens como um mecanismo de segurança para evitar que itens não utilizados ocupem memória por um longo período de tempo.
  • Mantenha apenas valores necessários na memória.

    Por exemplo, para um jogo de casa 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 em sua estrutura de dados.

  • Use retrocesso exponencial para ajudar a ficar abaixo dos limites de solicitações de API.

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

  • Divida grandes estruturas de dados em várias menores por meio de sharding.

    É frequentemente 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 acessadas frequentemente 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.

  • Inscreva-se em Serviços Estendidos.

    Você pode aumentar suas cotas de Limite de Armazenamento e Solicitações ao se inscrever em Serviços Estendidos.

Observabilidade

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

A tabela a seguir lista e descreve todos os códigos de status das respostas da API disponíveis nos gráficos de 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 ao qual um erro se relaciona, veja Limites e Cotizações.

Código de statusDescrição
SucessoSucesso.
DataStructureMemoryOverLimitExcede o limite de tamanho de memória da estrutura de dados (100 MB).
DataUpdateConflictConflito devido a atualização concorrente.
AcessoNegadoNão autorizado a acessar os dados do jogo. Esta solicitação não consome unidades de solicitação nem usa cota.
ErroInternoErro interno.
SolicitaçãoInválidaA solicitação não possui as informações necessárias ou possui informações malformadas.
DataStructureItemsOverLimitExcede o limite de contagem de itens da estrutura de dados (1M).
NenhumItemEncontradoNenhum 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 unidade de solicitação da estrutura de dados (100.000 unidades de solicitação por minuto).
PartitionRequestsOverLimitExcede o limite de unidade de solicitação da partição.
TotalRequestsOverLimitExcede o limite de unidade de solicitação em nível de universo.
TotalMemoryOverLimitExcede a cota de memória em nível de universo.
ItemValueSizeTooLargeO tamanho do valor excede o limite (32 KB).

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
ErroInternoErro Interno.
LocalNãoPublicadaVocê deve publicar este local para usar o MemoryStoreService.
AcessoClienteInválidoMemoryStoreService deve ser chamado do servidor.
TempoDeExpiraçãoInválidoO campo 'expiração' deve estar entre 0 e 3.888.000.
SolicitaçãoInválidaNão foi possível converter o valor para json.
SolicitaçãoInválidaNão foi possível converter sortKey em um número ou string válido.
TransformCallbackFailedFalha ao invocar a função de callback de transformação.
RequestThrottledSolicitações recentes de MemoryStores atingiram um ou mais limites.
UpdateConflictExcedeu 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 certo intervalo de tempo, como 30 segundos.
  • Use o gráfico de Contagem de Solicitações por Status para verificar se você está recebendo mais respostas de Sucesso do que NenhumItemEncontrado. Limite a quantidade de vezes que você atinge MemoryStoreService com uma solicitação falhada.
  • Implemente um pequeno atraso entre as 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 de mapa hash se você receber uma quantidade significativa de respostas PartitionRequestsOverLimit em chamadas de mapa hash.
    • Reduza ou agrupe chamadas para estruturas de dados específicas ou chaves de mapa hash se você ver respostas PartitionRequestsOverLimit.
    • Implemente um retrocesso exponencial para encontrar uma taxa razoável de solicitações a serem enviadas.
TotalRequestsOverLimit
DataStructureItemsOverLimit
DataStructureMemoryOverLimit
TotalMemoryOverLimit
DataUpdateConflict
  • Implemente um pequeno atraso entre as solicitações para evitar que várias solicitações atualizem a mesma chave ao mesmo tempo.
  • Para mapas ordenados, use a função de callback no método MemoryStoreSortedMap:UpdateAsync() para abortar uma solicitação após um certo número de tentativas, como o seguinte exemplo de código mostra:
  • 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("feito")
  • Investigue para ver se você está chamando MemoryStoreService de forma eficiente para evitar conflitos. Idealmente, você não deve enviar solicitações em excesso.
  • Remova consistentemente itens uma vez que eles sejam lidos usando o método MemoryStoreQueue:RemoveAsync() para filas e MemoryStoreSortedMap:RemoveAsync() para mapas ordenados.
Erro Interno
SolicitaçãoInválida
  • 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 Estúdio

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

Os testes no Estúdio 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, uma vez que você é o único usuário para testes no Estúdio. Ao testar a partir do Estúdio, você também pode notar uma latência ligeiramente maior e taxas de erro elevadas em comparação com o uso na produção devido a algumas verificações adicionais que são realizadas para verificar acesso e permissões.

Para informações sobre como depurar um armazenamento em memória em jogos ao vivo ou ao testar no estúdio, 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.