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 armazenamento de dados de alta velocidade e baixa latência que fornece armazenamento rápido em memória acessível 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, porque são mais rápidos de acessar e desaparecem quando atingem a vida útil máxima.Para dados que precisam persistir através de sessões, use armazenamentos de dados.

Estruturas de dados

Em vez de acessar diretamente dados brutos, os armazenamentos de memória têm três estruturas de dados primitivas compartilhadas entre servidores para processamento rápido: mapa ordenado, fila e mapa de hashes.Cada estrutura de dados é uma boa opção para determinados casos de uso:

  • Matchmaking baseado em habilidades - Salve informações do usuário, como nível de habilidade, em uma fila compartilhada entre os servidores e use servidores de lobby para executar o matchmaking periodicamente.
  • Negociação e leilão entre servidores - Habilite negociação universal entre diferentes servidores, onde os usuários podem ofertar itens com preços em tempo real que mudam, com um mapa ordenado de pares de chave-valor .
  • Tabelas de classificação globais - Armazenar e atualizar classificações de 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 de hashes compartilhado, onde os usuários podem utilizar itens de inventário simultaneamente uns com os outros.
  • Armazenamento em cache para dados persistentes - Sincronize e copie seus dados persistentes em um armazenamento de memória para um mapa de hash que possa atuar como cache e melhorar o performanceda sua experiência.

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

Limites e quotas

Para manter a escalabilidade e o performancedo sistema, os armazenamentos de memória têm quotas de uso de dados para o tamanho da memória, solicitações de API e o tamanho da estrutura de dados.

Armazenamentos de memória têm uma política de expulsão baseada no tempo de expiração, também conhecido como tempo para viver (TTL).Os itens são expulsos após expirarem e a quota de memória é liberada para novas entradas.Quando você atinge o limite de memória, todas as solicitações de escrita posteriores falham até que os itens expirem ou você os exclua manualmente.

Quota de tamanho de memória

O limite de memória limita a quantidade total de memória que uma experiência pode consumir.Não é um valor fixo.Em vez disso, muda ao longo do tempo dependendo do número de usuários na experiência de acordo com a seguinte fórmula: 64KB + 1KB * [number of users] .A quota se aplica no nível de experiência em vez do nível do servidor.

Quando os usuários se juntam à experiência, a quota de memória adicional está disponível imediatamente.Quando os usuários deixam a experiência, a quota não diminui imediatamente.Há um período de rastreamento de oito dias antes da quota reavaliar para um valor mais baixo.

Depois que sua experiência atinge a quota de tamanho de memória, quaisquer solicitações de API que aumentem o tamanho da memória sempre falham.Pedidos que diminuem ou não alteram o tamanho da memória ainda têm sucesso.

Com o painel de observabilidade observabilidade, você pode ver a quota de tamanho de memória da sua experiência em tempo real usando o gráfico Usagem de Memória .

Limites de solicitações de API

Para limites de solicitações de API, há uma quota de unidade de solicitação que se aplica a todas as chamadas MemoryStoreService.A cota é 1000 + 100 * [number of concurrent users] unidades de solicitação por minuto.

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

  • MemoryStoreSortedMap:GetRangeAsync()

    Consume 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()

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

  • MemoryStoreHashMap:UpdateAsync()

    Consume um mínimo de duas unidades.

  • MemoryStoreHashMap:ListItemsAsync()

    Consume [number of partitions scanned] + [items returned] unidades.

A quota de solicitações também é aplicada no nível da experiência em vez do 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 quota.Se você exceder a quota, receberá uma resposta de erro quando o serviço limitar suas solicitações.

Com a funcionalidade de observabilidade disponível, você pode ver a quantidade de unidades de solicitação da sua experiência em tempo real.

Limites de tamanho da estrutura de dados

Para um único mapa ou fila classificada, aplicam-se os seguintes limites de tamanho e número de itens:

  • 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 o padrão de uso de memória otimizado e evitar atingir os limites de limite, siga essas melhores práticas:

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

  • Defina o tempo de expiração para o menor período 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 tempo mais curto possível pode limpar automaticamente os dados antigos para impedi-los de preencher sua quota de uso de memória.

    • Não armazene uma grande quantidade de dados com uma longa expiração, pois corre o risco de exceder sua quota de memória e potencialmente causar problemas que possam quebrar toda a sua experiência.
    • Sempre exclua explicitamente itens desnecessários ou defina uma data de expiração de item curta.
    • Em geral, você deve usar exclusão explícita para liberar memória e expiração de itens como mecanismo de segurança para impedir que itens não utilizados ocupem memória por um período de tempo prolongado.
  • Apenas mantenha os valores necessários em memória.

    Por exemplo, para uma experiência de casa de leilões, você só precisa manter a maior oferta.Você pode usar MemoryStoreSortedMap:UpdateAsync() em uma chave para manter a maior oferta, ao invés de manter todas as ofertas em sua estrutura de dados.

  • Use retrocesso 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, então quatro, oito, etc.em vez de enviar constantemente solicitações para MemoryStoreService para obter a resposta correta.

  • Divida as estruturas de dados gigantescas em várias menores por fragmentação.

    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 use prefixos para suas chaves, considere separar cada prefixo em seu próprio mapa ordenado.Para uma experiência especialmente popular, você pode até mesmo separar os usuários em vários mapas com base nos últimos dígitos de seus IDs de usuário.

  • Comprimir valores armazenados.

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

Observabilidade

O Painel de Observabilidade fornece insights e análises para monitorar e solucionar problemas de uso do armazenamento de memória.Com gráficos de atualização em tempo real sobre diferentes aspectos do uso de memória e solicitações de API, você pode acompanhar o padrão de uso de memória da sua experiência, ver as quotas atribuídas 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 de respostas da API disponíveis nos gráficos Contagem de Pedidos por Status e Pedidos 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 a que um erro se refere, veja Limites e Cotações.

Código de códigoDescrição
SucessoSucesso.
DataStructureMemoryOverLimitExcede o limite de memória de nível de estrutura de dados (100MB).
Conflito de Atualização de DataConflito devido à atualização simultânea.
Acesso NegadoNão autorizado a acessar dados de experiência. Este pedido não consome unidades de solicitação ou usa quota.
Erro InternoErro interno.
Solicitação InválidaO pedido não tem informações necessárias ou tem informações mal formatadas.
Itens de Estrutura de Dados Sobre LimiteExcede o limite de número de itens da estrutura de dados (1M).
Nenhum item encontradoNenhum item encontrado em MemoryStoreQueue:ReadAsync() ou MemoryStoreSortedMap:UpdateAsync(). ReadAsync() pesquisa a cada 2 segundos e retorna este código de status até encontrar itens na fila.
Requisitos de Estrutura de Dados Sobre LimiteExcede o limite de unidade de solicitação de nível de estrutura de dados (100.000 solicitações por minuto).
Requisitos de Partição Sobre LimiteExcede o limite de unidade de solicitação de partição.
TotalRequestsOverLimitExcede o limite de unidade de solicitação de nível do universo.
TotalMemoryOverLimitExcede a quota de memória de nível do universo.
ItemValueSizeTooLarge Muito grandeO tamanho do valor excede o limite (32KB).

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

Código de códigoDescrição
Erro InternoErro interno.
Local Não PublicadoVocê deve publicar este local para usar o MemoryStoreService.
Acesso de Cliente InválidoO MemoryStoreService deve ser chamado do servidor.
Tempo de Expiração InválidoO tempo do campo 'expiração' deve estar entre 0 e 3,888,000.
Solicitação InválidaNão foi possível converter o valor para json.
Solicitação InválidaNão foi possível converter sortKey em um número ou string / cadeia / textoválido.
TransformCallbackFailedFalha ao invocar a função de retorno de transformação.
Solicitação AtrasadaPedidos recentes de MemóriaStores atingiram um ou mais limites.
Atualizar ConflitoExcedeu 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 ao salvar informações em outra variável e verificar novamente após um determinado período de tempo, como 30 segundos.:
  • Use o gráfico de Contagem de Solicitações por Status para verificar que você está recebendo mais Respostas de Sucesso do que NoItemFounds .Limite o número de vezes que você atinge MemoryStoreService com um solicitar / pedirfalhado.:
  • Implemente um pequeno atraso entre solicitações.:
  • Siga as melhores práticas de incluindo:
    • Fragmentar suas estruturas de dados se você receber uma quantidade significativa de Solicitações de Estrutura de Dados Sobre Limite / Solicitações de Partição Sobre Limite respostas.:
    • Implemente um recuo exponencial para encontrar uma taxa razoável de solicitações para enviar.
TotalRequestsOverLimit
Itens de Estrutura de Dados Sobre Limite
DataStructureMemoryOverLimit
TotalMemoryOverLimit
Conflito de Atualização de Data
  • Implemente um pequeno atraso entre solicitações para evitar que várias solicitações atualizem a mesma chave ao mesmo tempo.:
  • Para mapas ordenados, use a função de retorno de chamada no método MemoryStoreSortedMap:UpdateAsync() para cancelar um pedido após um certo número de tentativas, como mostra o seguinte exemplo de código:
  • Example of Aborting Request

    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 is "..item.highestBid)
    return nil
    end, 1000)
    end
    placeBid("MyItem", 50)
    placeBid("MyItem", 40)
    print("done")
  • Investigue para ver se você está chamando MemoryStoreService eficientemente para evitar conflitos.Idealmente, você não deve enviar solicitações excessivas.:
  • Remova consistentemente itens uma vez que eles são lidos usando o método MemoryStoreQueue:RemoveAsync() para filas e MemoryStoreSortedMap:RemoveAsync() para mapas classificados.
Erro interno
  • Verifique a página de status do Roblox.
  • Envie um relatório de bug descrevendo o problema com o ID do Universo da sua experiência.
Solicitação Inválida
  • Certifique-se de incluir parâmetros corretos e válidos em sua solicitar / pedir. Exemplos de parâmetros inválidos incluem:
    • Uma string vazia
    • Uma string que excede o limite de comprimento
    • >

ItemValueSizeTooLarge Muito grande
  • Fragmentar ou dividir o valor do item em várias chaves.
    • Para organizar chaves agrupadas, classifique-as alfabeticamente adicionando um prefix à chave.
  • Codificar ou compactar valores armazenados.

Teste e debugue no Studio

Os dados em MemoryStoreService estão isolados entre o Studio e a produção, então alterar os dados no Studio não afeta o comportamento da produção.Isso significa que suas chamadas de API do Studio não têm acesso a dados de produção, permitindo que você teste com segurança armazenamentos de memória e novos recursos antes de ir para a produção.

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

Para obter informações sobre como depurar um armazenamento de memória em experiências ao vivo ou ao testar no estúdio, use Console de Desenvolvedor.