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.
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ódigo | Descrição |
---|---|
Sucesso | Sucesso. |
DataStructureMemoryOverLimit | Excede o limite de memória de nível de estrutura de dados (100MB). |
Conflito de Atualização de Data | Conflito devido à atualização simultânea. |
Acesso Negado | Não autorizado a acessar dados de experiência. Este pedido não consome unidades de solicitação ou usa quota. |
Erro Interno | Erro interno. |
Solicitação Inválida | O pedido não tem informações necessárias ou tem informações mal formatadas. |
Itens de Estrutura de Dados Sobre Limite | Excede o limite de número de itens da estrutura de dados (1M). |
Nenhum item encontrado | Nenhum 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 Limite | Excede 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 Limite | Excede o limite de unidade de solicitação de partição. |
TotalRequestsOverLimit | Excede o limite de unidade de solicitação de nível do universo. |
TotalMemoryOverLimit | Excede a quota de memória de nível do universo. |
ItemValueSizeTooLarge Muito grande | O 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ódigo | Descrição |
---|---|
Erro Interno | Erro interno. |
Local Não Publicado | Você deve publicar este local para usar o MemoryStoreService. |
Acesso de Cliente Inválido | O MemoryStoreService deve ser chamado do servidor. |
Tempo de Expiração Inválido | O tempo do campo 'expiração' deve estar entre 0 e 3,888,000. |
Solicitação Inválida | Não foi possível converter o valor para json. |
Solicitação Inválida | Não foi possível converter sortKey em um número ou string / cadeia / textoválido. |
TransformCallbackFailed | Falha ao invocar a função de retorno de transformação. |
Solicitação Atrasada | Pedidos recentes de MemóriaStores atingiram um ou mais limites. |
Atualizar Conflito | Excedeu 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:
Erro | Opções de solução de problemas |
---|---|
DataStructureRequestsOverLimit / PartitionRequestsOverLimit |
|
TotalRequestsOverLimit | |
Itens de Estrutura de Dados Sobre Limite |
|
DataStructureMemoryOverLimit | |
TotalMemoryOverLimit | |
Conflito de Atualização de Data |
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 |
|
Solicitação Inválida |
|
ItemValueSizeTooLarge Muito grande |
|
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.