MemoryStoreService é um serviço de dados de alto desempenho e baixa latência que fornece armazenamento de dados 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 efeitos de duração que mudam rapidamente e não precisam ser duradouros, porque el
Estruturas de Dados
Em vez de acessar diretamente dados brutos, armazenamentos de memória têm três estruturas de dados primitivas compartilhadas entre servidores para processamento rápido: mapa sortido, fila e mapa de hashes. Cada estrutura de dados é uma boa opção para alguns casos de uso:
- Criação de partidas baseada em habilidade - Salve informações do usuário, como o nível de habilidade, em uma fila compartilhada entre servidores e use servidores de lobby para executar a criação de partidas regularmente.
- Negociação e leilão entre servidores - Habilite a negociação universal entre diferentes servidores, onde os usuários podem bidar em itens com preços de mudança de tempo real, com um mapa sortudo de pares de valor de chave.
- Tabelas de classificação globais - Armazena e atualiza 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 hash compartilhado , onde os usuários podem usar itens de inventário concomitantemente um com o outro.
- Cache for Persistent Data - Sincronize e copie seus dados persistentes em um armazenamento de dados para um armazenamento de memória hash mapa que pode atuar como um cache e melhorar o performancede sua experiência.
Em geral, se você precisar acessar dados com base em uma chave específica, use um mapa de hashes. Se você precisar que os dados sejam ordenados, use um mapa sortido. Se você precisar processar seus dados em um determinado ordenado, use uma fila.
Limites e Quotas
Para manter a escalabilidade e 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 tamanho da estrutura de dados.
Os armazenamentos de memória têm uma política de expulsão com base no tempo de expiração, também conhecido como tempo para viver (TTL). Os itens são expulsos depois que expiram, e o quota de memória é liberado para novas entradas. Quando você atinge o limite de memória, todos os pedidos de gravação seguintes falharão até que os itens expirem ou você exclua manualmente.
Tamanho da 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, ele 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] . O limite aplica-se no nível da experiência em vez do nível do servidor.
Quando os usuários se juntam à experiência, o quota de memória adicional está disponível imediatamente. Quando os usuários saem da experiência, o quota não se reduz imediatamente. Existe um período de rastreamento de oito dias antes que o quota reavalie para um valor mais baixo.
Depois que sua experiência atinge o tamanho da memória, qualquer solicitação de API que aumente o tamanho da memória sempre falha. Solicitações que diminuem ou não alteram o tamanho da memória ainda são bem-sucedidas.
Com o painel de observabilidade, você pode ver o tamanho da memória do seu experimento em tempo real usando o gráfico Uso de Memória.
Limites de Pedido de API
Para limites de solicitação de API, há uma unidade de solicitação quota que se aplica a todas as chamadas da API MemoryStoreService. A quota é 1000 + 100 * [number de usuários concurrentes] unidades por minuto.
A maioria das chamadas da API só consome uma unidade de pedido, 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 contará como 10 unidades de solicitação. Se ele retornar uma resposta vazia, contará como uma unidade de solicitação.
Consume unidades com base no número de itens retornados, como MemoryStoreSortedMap:GetRangeAsync() ', mas consume uma unidade adicional a cada dois segundos ao ler. 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 de partitions scanned] + [items returned] unidades.
O quórum de pedidos também é aplicado no nível da experiência, em vez do nível do servidor. Isso fornece flexibilidade para alocar os pedidos entre os servidores, desde que a taxa total de pedidos não exceda o quórum. Se você exceder o quórum, você receberá uma resposta de erro quando o serviço limitar suas solicitações.
Com a observabilidade função disponível, você pode ver o quórum de unidade de pedido de sua experiência em tempo real.
Limites de Tamanho da Estrutura de Dados
Para um único mapa ou fila sortida, os seguintes limites de tamanho e contagem de itens aplicam-se:
- Número máximo de itens: 1,000,000
- Tamanho máximo total (incluindo chaves para mapas classificados): 100 MB
Limites de Per-Partition
Veja Limites de Per-Partition.
Melhores Práticas
Para manter seu padrão de uso de memória ótimo e evitar apertar os limites, siga essas melhores práticas:
Remova itens processados. Limpe consistentemente os itens lidos usando o método MemoryStoreQueue:RemoveAsync() para filas e MemoryStoreSortedMap:RemoveAsync() para mapas sortidos pode liberar memória e manter a estrutura de dados atualizada.
Defina o tempo de expiração para o menor tempo possível ao adicionar dados. Embora o tempo de expiração padrão seja 45 dias para ambos Class.MemoryStoreQueue:AddAsync() e Class.MemoryStoreSortedMap:SetAsync() , definir o tempo mais curto possível pode limpar automaticamente os dados antigos para impedir que eles ocupem sua memória de uso.
- Não armazene uma grande quantidade de dados com uma longa expiração, pois isso pode exceder sua quota de memória e potencialmente causar problemas que podem interromper sua experiência inteira.
- Sempre exclua itens não necessários ou configure uma expiração de itens curta.
- Normalmente, você deve usar exclusão explícita para liberar memória e expiração de itens como um mecanismo de segurança para impedir que itens não usados ocupem memória por um período de tempo Extendido.
Só mantenha os valores necessários na memória.
Por exemplo, para uma experiência de casa de leilão, você só precisa manter o lance mais alto. Você pode usar MemoryStoreQueue:UpdateAsync() em uma chave para manter o lance mais alto, em vez de manter todos os lances em sua estrutura de dados.
Use desconectar exponencial para ajudar a manter abaixo dos limites de solicitação da API.
Por exemplo, se você receber um DataUpdateConflict, você pode tentar novamente depois de dois segundos, então quatro, oito, etc. em vez de enviar pedidos constantemente para Class.MemoryStoreService para obter a resposta correta.
Divida estruturas de dados gigantes em várias menores por sharding .
Muitas vezes, é mais fácil gerenciar dados em estruturas menores do que armazenar tudo em uma única estrutura de dados grande. Essa abordagem também pode ajudar a evitar limites de uso e taxas. Por exemplo, se você tiver um mapa sorteado que usa prefixos para suas chaves, considere separar cada prefixo em seu próprio mapa sorteado. Para uma experiência popular, você pode até separar os usuários em vários mapas com base nos últimos dígitos de seus ID
Compre valores armazenados.
Por exemplo, considere usar o algoritmo LZW para reduzir o tamanho do valor armazenado.
Observabilidade
O Painel de Observabilidade da Memória fornece insights e análises de monitoramento e solução de problemas para acompanhar e solucionar problemas relacionados ao uso de armazenamento de memória. Com gráficos atualizados em tempo real sobre diferentes aspectos do uso de armazenamento de memória e solicitações de API, você pode rastrear o padrão de uso de memória de sua experiência, ver os quotas atribuídos atuais e monitorar o status da API e identificar possíveis problemas para a otimização de desem
A tabela a seguir lista e descreve todos os códigos de status de respostas de API disponíveis no Painel de Observabilidade's Pedido por Status e Solicitações por API x Status gráficos. Para mais informações sobre como resolver esses erros, see Troubleshooting . Para o limite ou limite específico que um erro relaciona, see 1>Limits and Quot
Código de Status | Descrição |
---|---|
Sucesso | Sucesso. |
Limite de Memória de Estrutura de Dados | Excede o limite de tamanho da memória da estrutura de dados (100MB). |
Conflito de Dados | Conflito devido a uma atualização concomitante. |
Negado de Acesso | Não autorizado a acessar dados de experiência. Este pedido não consome unidades de pedido ou usa quota. |
Erro Interno | Erro interno. |
Solicitação inválida | A solicitação não tem informações necessárias ou tem informações malformadas. |
Limite de Itens de Estrutura de Dados | Excede o limite de nível de item da estrutura de dados (1M). |
Nenhum item encontrado | Nenhum item encontrado em MemoryStoreQueue:ReadAsync() ou MemoryStoreSortedMap:UpdateAsync() . ReadAsync() polls a cada 2 segundos e retorna este código de status até que encontre itens na fila. |
Limite de Solicitações de Dados | Excede o limite de solicitação de nível de estrutura de dados (100.000 unidades de solicitação por minuto). |
Limite de Solicitações de Partição | Excede o limite de unidade de pedido de partição. |
Limite Total de Solicitações | Excede o limite de unidade de pedido do nível do universo. |
Limite Total de Memória | Excede o quórum de memória de nível do universo. |
ItemValueSizeTooLarge | O tamanho do valor excede o limite (32KB). |
A tabela a seguir lista códigos do lado do cliente, que não estão disponíveis no Painel de Observabilidade.
Código de Status | Descrição |
---|---|
Erro Interno | Erro Interno. |
Lugar não publicado | Você deve publicar este lugar para usar o MemoryStoreService. |
Acesso Inválido ao Cliente | O MemoryStoreService deve ser chamado do servidor. |
Expiração de Tempo Inválida | O tempo de 'expiração' da campo deve ser entre 0 e 3,888,000. |
Solicitação inválida | Não foi possível convertter o valor em JSON. |
Solicitação inválida | Não foi possível convertar o sortKey em um número ou string / cadeia / textoválido. |
Transformação de retorno de chamada falhou | Falha ao invocar a função de chamada de transformação. |
RequestThrottled | Solicitações de armazenamento de memória recente atingiram um ou mais limites. |
Conflito de Atualização | Número máximo de tentativas excedido. |
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 |
---|---|
DataStructureCommands / PartitionCommands |
|
Limite Total de Solicitações | |
Limite de Itens de Estrutura de Dados |
|
Limite de Memória de Estrutura de Dados | |
Limite Total de Memória | |
Conflito de Dados | implementa um atraso pequeno entre solicitações para evitar várias solicitações atualizando a mesma chave ao mesmo tempo. Para mapas sortidos, use a função de retorno de chamada no método Class.MemoryStoreSortedMap:UpdateAsync() para cancelar uma solicitação após uma certa quantidade |
Erro Interno |
File um relatório de bug descrevendo o problema com o ID do Universo da sua experiência. |
Solicitação inválida |
|
ItemValueSizeTooLarge |
|
Testando e Debugando no Studio
Os dados em MemoryStoreService são isolados entre o Studio e a produção, então alterar os dados no Studio não afeta o comportamento de produção. Isso significa que suas chamadas da API do Studio não acessam dados de produção, permitindo que você teste com segurança armazenamentos de memória e novos recursos antes de ir à produção.
Testes do Studio têm os mesmos limites e quotas que a produção. Para quotas calculadas com base no número de usuários, a quota resultante pode ser muito pequena, pois você é o único usuário para testes do Studio. Ao testar do Studio, você também pode notar um ligeiro aumento de latência e taxas de erro elevadas em comparação com o uso na produção devido a alguns controles adicionais que são executados para verificar acesso e permissões.
Para obter informações sobre como debugar um armazenamento de memória em experiências ao vivo ou ao testar em estúdio, use Console de Desenvolvedor.