Práticas recomendadas para usar o Spanner como um banco de dados de jogos

Neste documento, descrevemos as práticas recomendadas para usar o Spanner como o principal banco de dados de back-end para armazenamento de estado de jogos. Use o Spanner no lugar de bancos de dados comuns para armazenar dados de autenticação dos jogadores e de inventário. Este documento destina-se a engenheiros de back-end de jogos que trabalham em armazenamento de estado de longo prazo e operadores e administradores de infraestrutura de jogos compatíveis com o Google Cloud.

Os jogos multijogador e on-line evoluíram para exigir estruturas de banco de dados cada vez mais complexas para rastrear direitos, estado e dados de inventário do jogador. Aumentar a base de jogadores e aumentar a complexidade do jogo levou a soluções de banco de dados que são um desafio de escalonamento e gerenciamento, exigindo frequentemente o uso de fragmentação ou de clustering (links em inglês). Manter o controle de itens valiosos no jogo ou do progresso mais relevante dos jogadores normalmente exige transações, e é um desafio trabalhar em muitos tipos de bancos de dados distribuídos.

O Spanner é o primeiro serviço de banco de dados escalonável, de nível empresarial e altamente consistente criado para a nuvem para combinar os benefícios da estrutura de banco de dados relacional com escala horizontal não relacional. Muitas empresas de jogos descobriram que é adequado substituir bancos de dados de estado e autenticação de jogos em sistemas em escala de produção. É possível escalonar para melhorar o desempenho ou o armazenamento usando o console do Google Cloud para adicionar nós. O Spanner pode lidar de forma transparente com a replicação global com consistência forte, eliminando a necessidade de gerenciar réplicas regionais.

Neste documento de práticas recomendadas, falamos sobre os itens a seguir:

  • Conceitos importantes do Spanner e diferenças dos bancos de dados normalmente usados em jogos.
  • Quando o Spanner é o banco de dados certo para seu jogo.
  • Padrões a serem evitados ao usar o Spanner para jogos.
  • Como projetar suas operações de banco de dados com o Spanner como banco de dados do jogo.
  • Como modelar seus dados e criar um esquema para conseguir o melhor desempenho com o Spanner.

Terminologia

Direitos
Jogos, expansões ou compras no app que pertençam a um jogador.
Informações de identificação pessoal (PII, na sigla em inglês)
Em jogos, informações que normalmente incluem endereço de e-mail e dados da conta para pagamentos, como número de cartão de crédito e endereço de faturamento. Em alguns mercados, essas informações podem incluir um número de identificação nacional.
Banco de dados do jogo
Um banco de dados que armazena o progresso do jogador e o inventário de um jogo.
Banco de dados de autenticação
Um banco de dados que inclui os direitos do jogador e as PII que os jogadores usam quando fazem uma compra. O banco de dados de autenticação também é conhecido como o banco de dados da conta ou banco de dados do jogador. Esse banco de dados às vezes é combinado com o banco de dados do jogo, mas eles são frequentemente separados em estúdios ou editores que têm vários títulos.
Transação
Uma transação de banco de dados (em inglês): um conjunto de operações de gravação que têm um efeito de tudo ou nada. Ou a transação é bem-sucedida e todas as atualizações entram em vigor ou o banco de dados é retornado a um estado que não inclui nenhuma das atualizações da transação. Nos jogos, as transações do banco de dados são mais importantes ao processar pagamentos e ao atribuir a propriedade de um inventário ou moeda no jogo.
Sistema de gerenciamento de banco de dados relacional (RDBMS, na sigla em inglês)
Um sistema de banco de dados com base em tabelas e linhas que fazem referência mútua. SQL Server, MySQL e (menos comumente) Oracle® são exemplos de bancos de dados relacionais usados em jogos. Eles são frequentemente usados porque podem fornecer metodologias familiares e garantias fortes em relação a transações.
Banco de dados NoSQL
Bancos de dados que não são estruturados relacionalmente. Esses bancos de dados estão sendo mais usados em jogos porque têm muita flexibilidade quando o modelo de dados é alterado. Os bancos de dados NoSQL incluem o MongoDB e o Cassandra.
Chave primária
Normalmente, a coluna que contém o ID exclusivo para itens de inventário, contas de jogadores e transações de compra.
Instância
Um único banco de dados. Por exemplo, um cluster executa várias cópias do software de banco de dados, mas aparece como uma única instância no back-end do jogo.
Para os propósitos deste documento, uma única máquina executando uma cópia do software de banco de dados.
Réplica
Uma segunda cópia de um banco de dados. As réplicas são usadas com frequência para recuperação de dados e alta disponibilidade ou para aumentar a capacidade de leitura.
Grupo
Várias cópias do software em execução em diversas máquinas que, juntas, aparecem como uma única instância no back-end do jogo. O cluster é usado para proporcionar escalonabilidade e disponibilidade.
Fragmento
Uma instância de um banco de dados. Muitos estúdios de jogos executam várias instâncias de banco de dados homogêneas, cada uma com um subconjunto dos dados do jogo. Cada uma dessas instâncias é chamada de fragmento. Geralmente, a fragmentação é feita para proporcionar desempenho ou escalonabilidade, sacrificando a eficiência do gerenciamento e aumentando a complexidade do app. A fragmentação no Spanner é implementada usando divisões.
Divisão
O Spanner divide seus dados em partes chamadas divisões, em que divisões individuais podem ser movidas independentemente umas das outras e atribuídas a servidores diferentes. Uma divisão é definida como um intervalo de linhas em uma tabela de nível superior (em outras palavras, não intercalada), em que as linhas são ordenadas pela chave primária. As chaves de início e término desse intervalo são chamadas de "limites de divisão". O Spanner adiciona e remove automaticamente limites de divisão, o que altera o número de divisões no banco de dados. O Spanner divide os dados com base na carga: ele adiciona limites de divisão automaticamente quando detecta alta carga de leitura ou gravação espalhada entre muitas chaves em uma divisão.
Ponto de acesso
Quando uma única divisão em um banco de dados distribuído, como o Spanner, contém registros que recebem uma grande parte de todas as consultas que vão para o banco de dados. Esse cenário não é o ideal porque reduz o desempenho.

Como usar o Spanner para jogos

Na maioria dos casos em que você está considerando um RDBMS para seu jogo, o Spanner é uma opção apropriada porque pode substituir efetivamente o banco de dados do jogo, o banco de dados de autenticação ou, em muitos casos, ambos.

Bancos de dados de jogo

O Spanner pode operar como uma única autoridade transacional mundial, o que o torna uma excelente opção para sistemas de inventário de jogos. Qualquer moeda ou item no jogo que possa ser negociado, vendido, presenteado ou transferido de um jogador para outro apresenta um desafio em back-ends de jogos em larga escala. Frequentemente, a fama de um jogo pode ultrapassar a capacidade de um banco de dados tradicional de lidar com tudo em um sistema de nó único. Dependendo do tipo de jogo, o banco de dados pode ter dificuldades com o número de operações necessárias para lidar com a carga do jogador e a quantidade de dados armazenados. Isso geralmente leva os desenvolvedores de jogos a fragmentar o banco de dados para melhorar o desempenho ou para armazenar tabelas cada vez maiores. Esse tipo de solução gera complexidade operacional e grande sobrecarga de manutenção.

Para reduzir essa complexidade, uma estratégia comum é executar regiões de jogos completamente separadas, sem nenhuma maneira de mover dados entre elas. Nesse caso, itens e moedas não podem ser negociados entre jogadores em diferentes regiões do jogo, porque os estoques em cada região são separados em bancos de dados distintos. No entanto, essa configuração sacrifica a experiência preferida do jogador, em favor da simplicidade operacional e do desenvolvedor.

Por outro lado, é possível permitir transações entre regiões em um banco de dados geograficamente fragmentado, mas geralmente com alto custo de complexidade. Essa configuração requer que as transações abranjam várias instâncias de banco de dados, gerando uma lógica complexa do lado do aplicativo, propensa a erros. Tentar receber bloqueios de transação em vários bancos de dados pode ter impactos significativos no desempenho. Além disso, não poder confiar em transações atômicas pode levar os jogadores a se aproveitar das falhas, como duplicação da moeda ou dos itens. Isso prejudica o ecossistema e a comunidade do jogo.

O Spanner pode simplificar sua abordagem de inventário e transações de moeda. Mesmo ao usar o Spanner para armazenar todos os seus dados de jogos em todo o mundo, ele oferece transações de leitura e gravação com propriedades mais fortes do que as tradicionais de atomicidade, consistência, isolamento e durabilidade (ACID, na sigla em inglês). Com a escalonabilidade do Spanner, isso significa que os dados não precisam ser fragmentados em instâncias de banco de dados separadas quando é necessário mais desempenho ou armazenamento. Em vez disso, basta adicionar mais nós. Além disso, a alta disponibilidade e a resiliência de dados para os quais os jogos costumam realizar o clustering dos bancos de dados são manipulados de forma transparente pelo Spanner, não exigindo configuração ou gerenciamento extra.

Bancos de dados de autenticação

Os bancos de dados de autorização também podem ser bem atendidos pelo Spanner, especialmente se você quiser padronizar um único RDBMS no nível do seu estúdio ou editor. Ainda que os bancos de dados de autenticação para jogos geralmente não exijam a escala do Spanner, as garantias transacionais e a alta disponibilidade de dados podem torná-lo atraente. A replicação de dados no Spanner é transparente, síncrona e integrada. O Spanner tem configurações que oferecem 99,99% ("quatro noves") ou 99,999% ("cinco noves") de disponibilidade, este último correspondente a menos de cinco minutos e meio de indisponibilidade em um ano. Esse tipo de disponibilidade o torna uma boa opção para o caminho de autenticação essencial exigido no início de cada sessão do jogador.

Práticas recomendadas

Nesta seção, fornecemos recomendações sobre como usar o Spanner no design de jogos. É importante modelar os dados do jogo para aproveitar os recursos exclusivos oferecidos pelo Spanner. É possível acessar o Spanner usando a semântica do banco de dados relacional, mas alguns pontos de design do esquema podem ajudar a aumentar seu desempenho. A documentação do Spanner tem recomendações detalhadas de design de esquema que podem ser analisadas, mas as seções a seguir são algumas das práticas recomendadas para bancos de dados de jogos.

As práticas neste documento são baseadas em experiências de uso do cliente e estudos de caso.

Usar UUIDs como códigos de jogadores e personagens

A tabela de jogadores geralmente tem uma linha para cada jogador e a respectiva moeda, progresso ou outros dados no jogo que não são mapeados facilmente para as diferentes linhas da tabela do inventário. Se seu jogo permitir que os jogadores tenham um progresso salvo separado para vários personagens, como muitos jogos multijogador massivos e persistentes, essa tabela normalmente contém uma linha para cada personagem. O padrão é o mesmo.

Recomendamos usar um identificador de personagem ou de jogador (ID de personagem) globalmente exclusivo como a chave primária da tabela de personagens. Também recomendamos o uso do Identificador universalmente exclusivo (UUID, na sigla em inglês) v4 porque ele distribui os dados dos jogadores para os nós do banco de dados e pode ajudar você a conseguir mais desempenho com o Spanner.

Usar intercalação para tabelas de inventário

Muitas vezes, a tabela de inventário contém itens inseridos no jogo, como cards, unidades ou equipamentos de personagens. Normalmente, um único jogador tem muitos itens no inventário. Cada item é representado por uma única linha na tabela.

Assim como outros bancos de dados relacionais, uma tabela de inventário no Spanner tem uma chave primária que é um identificador globalmente exclusivo para o item, conforme ilustrado na tabela a seguir.

itemID type playerID
7c14887e-8d45 1 6f1ede3b-25e2
8ca83609-bb93 40 6f1ede3b-25e2
33fedada-3400 1 5fa0aa7d-16da
e4714487-075e 23 5fa0aa7d-16da
d4fbfb92-a8bd 14 5fa0aa7d-16da
31b7067b-42ec 3 26a38c2c-123a

No exemplo de tabela de inventário, itemID e playerID são truncados para legibilidade. Uma tabela de inventário real também conterá muitas outras colunas que não estão incluídas no exemplo.

Uma abordagem típica em um RDBMS para controlar a propriedade do item é usar uma coluna como uma chave externa que contém o código de jogador do proprietário atual. Essa coluna é a chave primária de uma tabela de banco de dados separada. No Spanner, é possível usar a intercalação, que armazena as linhas de inventário próximas à linha da tabela de jogadores associada para melhorar o desempenho. Ao usar tabelas intercaladas, tenha em mente o seguinte:

  • É necessário manter o total de dados na linha do jogador e todas as linhas de inventário descendentes abaixo de 4 GiB. Essa restrição normalmente não é um problema com um design de modelo de dados apropriado.
  • Não é possível gerar um objeto sem um proprietário. Evite objetos sem dono no design do jogo, desde que a limitação seja conhecida antecipadamente.

Indexação de design para evitar pontos de acesso

Muitos desenvolvedores de jogos implementam índices em muitos dos campos de inventário para otimizar certas consultas. No Spanner, criar ou atualizar uma linha com dados nesse índice gera uma carga de gravação extra proporcional ao número de colunas indexadas. É possível melhorar o desempenho do Spanner eliminando índices que não são usados com frequência ou implementando esses índices de outras maneiras que não afetam o desempenho do banco de dados.

No exemplo a seguir, há uma tabela para registros de longo prazo referentes à maior pontuação do jogador:

CREATE TABLE Ranking (
        PlayerID STRING(36) NOT NULL,
        GameMode INT64 NOT NULL,
        Score INT64 NOT NULL
) PRIMARY KEY (PlayerID, GameMode)

Essa tabela contém o código do jogador (UUIDv4), um número que representa um modo de jogo, estágio ou temporada, e a pontuação do jogador.

Para acelerar as consultas que filtram o modo de jogo, considere o índice a seguir:

CREATE INDEX idx_score_ranking ON Ranking (
        GameMode,
        Score DESC
)

Se todos jogarem o mesmo modo de jogo chamado 1, esse índice criará um ponto de acesso em que GameMode=1. Se você quiser uma classificação para este modo de jogo, o índice só verifica as linhas que contêm GameMode=1, retornando a classificação rapidamente.

Se você alterar a ordem do índice anterior, poderá resolver esse problema de ponto de acesso:

CREATE INDEX idx_score_ranking ON Ranking (
        Score DESC,
        GameMode
)

Esse índice não cria um ponto de acesso significativo para os jogadores que competem no mesmo modo de jogo, desde que suas pontuações estejam distribuídas no intervalo possível. No entanto, receber pontuações não será tão rápido quanto no índice anterior, porque a consulta verifica todas as pontuações de todos os modos para determinar se GameMode=1.

Como resultado, o índice reordenado resolve o ponto de acesso anterior no modo de jogo, mas ainda tem espaço para melhorias, conforme ilustrado no design a seguir.

CREATE TABLE GameMode1Ranking (
        PlayerID STRING(36) NOT NULL,
        Score INT64 NOT NULL
) PRIMARY KEY (PlayerID)

CREATE INDEX idx_score_ranking ON Ranking (
        Score DESC
)

Recomendamos mover o modo de jogo para fora do esquema da tabela e usar uma tabela por modo, se possível. Ao usar esse método, quando você recupera as pontuações de um modo, consulta apenas uma tabela com pontuações para esse modo. Essa tabela pode ser indexada por pontuação para rápida recuperação de intervalos de pontuação sem perigo significativo de pontos de acesso (desde que as pontuações sejam bem distribuídas). No momento da gravação deste documento, o número máximo de tabelas por banco de dados no Spanner é 2.560, o que é mais do que suficiente para a maioria dos jogos.

Bancos de dados separados por locatário

Ao contrário de outras cargas de trabalho, em que recomendamos projetar para multilocação no Spanner usando diferentes valores de chave primária, para dados de jogos, recomendamos a abordagem mais tradicional de bancos de dados separados por locatário. As alterações de esquema são comuns com o lançamento de novos recursos em jogos com serviço ao vivo. O isolamento de locatários em um nível de banco de dados pode simplificar as atualizações de esquema. Essa estratégia também pode otimizar o tempo necessário para fazer backup ou restaurar os dados de um locatário, porque essas operações são executadas em um banco de dados inteiro de uma só vez.

Evitar atualizações incrementais de esquema

Ao contrário de alguns bancos de dados relacionais convencionais, o Spanner permanece operacional durante as atualizações do esquema. Todas as consultas no esquema antigo são retornadas (ainda que possam retornar menos rapidamente que o normal) e as consultas no novo esquema são retornadas à medida que se tornam disponíveis. É possível criar seu processo de atualização para manter seu jogo ativo durante as atualizações de esquema quando ele for executado no Spanner, desde que tenha em mente as restrições anteriores.

No entanto, se você solicitar outra alteração de esquema enquanto uma estiver sendo processada, a nova atualização ficará na fila e não ocorrerá até que todas as atualizações de esquema anteriores sejam concluídas. Evite essa situação planejando atualizações de esquema maiores, em vez de emitir muitas atualizações de esquema incrementais em um curto período. Para mais informações sobre atualizações de esquema, incluindo como realizar uma atualização de esquema que requer validação de dados, consulte a documentação de atualização de esquema do Spanner.

Considerar o tamanho e o acesso ao banco de dados

Ao desenvolver seus serviços de plataforma e servidor de jogos para usar o Spanner, considere como o jogo acessa o banco de dados e como dimensionar o banco de dados para evitar custos desnecessários.

Usar drivers e bibliotecas nativos

Ao desenvolver o Spanner, considere como seu código interage com o banco de dados. O Spanner oferece bibliotecas de cliente nativas para muitas linguagens conhecidas, que geralmente são ricas em recursos e têm bom desempenho. Os drivers JDBC também estão disponíveis e oferecem suporte às instruções da linguagem de manipulação de dados (DML, na sigla em inglês) e da linguagem de definição de dados (DDL, na sigla em inglês). Nos casos em que o Spanner é usado no novo desenvolvimento, recomendamos o uso das bibliotecas de cliente do Cloud para o Spanner. Ainda que as integrações típicas de mecanismos de jogo não tenham muita flexibilidade na seleção da linguagem, para os serviços de plataforma que acessam o Spanner, há casos em que clientes de jogos usam Java ou Go. Para aplicativos de alto rendimento, selecione uma biblioteca na qual seja possível usar o mesmo cliente Spanner para várias solicitações sequenciais.

Dimensionar o banco de dados para as necessidades de teste e produção

Durante o desenvolvimento, uma instância do Spanner de nó único provavelmente é suficiente para a maioria das atividades, incluindo testes funcionais.

Avaliar as necessidades do Spanner para produção

Ao passar do desenvolvimento para o teste e depois para a produção, é importante reavaliar o Spanner para garantir que seu jogo possa lidar com o tráfego de jogadores ao vivo.

Antes de passar para a produção, os testes de carga são cruciais para verificar se o back-end pode lidar com a carga durante a produção. Recomendamos executar testes de carga com o dobro da carga esperada na produção para estar preparado para picos de uso e casos em que seu jogo fique mais famoso do que o previsto.

Executar testes de carga usando dados reais

Executar um teste de carga com dados sintéticos não é suficiente. Também é preciso executar testes de carga usando dados e padrões de acesso o mais próximo possível do que é esperado na produção. Os dados sintéticos podem não detectar possíveis pontos de acesso no design do esquema do Spanner. Nada é melhor do que executar um teste Beta (aberto ou fechado) com jogadores reais para verificar como o Spanner se comporta com os dados de verdade.

O diagrama a seguir é um exemplo de esquema de tabela de jogadores de um estúdio de jogos que ilustra a importância do uso de testes beta de carga.

Lista de nomes de jogadores e um atributo para teste de carga.

O estúdio preparou esses dados com base nas tendências de um jogo anterior que eles operaram por alguns anos. A empresa esperava que o esquema representasse bem os dados nesse novo jogo.

Cada registro de jogador tem alguns atributos numéricos associados a ele que acompanham o progresso do jogador no jogo (como classificação e tempo de jogo). Para o atributo de exemplo usado na tabela anterior, os novos jogadores recebem um valor inicial de 50 que muda para um valor entre 1 e 100 à medida que o jogador avança.

O estúdio quer indexar esse atributo para acelerar consultas importantes durante o jogo.

Com base nesses dados, o Studio criou a seguinte tabela do Spanner, com uma chave principal usando PlayerID e um índice secundário em Attribute.

CREATE TABLE Player (
        PlayerID STRING(36) NOT NULL,
        Attribute INT64 NOT NULL
) PRIMARY KEY (PlayerID)

CREATE INDEX idx_attribute ON Player(Attribute)

E o índice foi consultado para encontrar até dez jogadores com Attribute=23, como este:

SELECT PlayerID
        FROM Player@{force_index=idx_attribute}
        WHERE Attribute = 23
        LIMIT 10

De acordo com a documentação sobre otimização do design de esquema, o Spanner armazena dados de índice da mesma forma que as tabelas, com uma linha por entrada de índice. Em testes de carga, esse modelo faz um trabalho aceitável de distribuição da carga de leitura e gravação do índice secundário em várias divisões do Spanner, conforme ilustrado no diagrama a seguir:

Os jogadores distribuídos por Spanner se dividem por atributo.

Ainda que os dados sintéticos usados no teste de carga sejam semelhantes ao estado estável do jogo, em que os valores Attribute são bem distribuídos, o design do jogo determina que todos os jogadores começam com Attribute=50. Como cada novo jogador começa com Attribute=50, quando novos jogadores entram, eles são inseridos na mesma parte do índice secundário idx_attribute. Isso significa que as atualizações são roteadas para a mesma divisão do Spanner, causando um ponto de acesso durante a janela de lançamento do jogo. Esse uso do Spanner é ineficiente.

Os jogadores no lançamento com o mesmo atributo criam um ponto de acesso em uma única divisão do Spanner.

No diagrama a seguir, adicionar uma coluna IndexPartition ao esquema após o lançamento resolve o problema do ponto de acesso, e os jogadores são distribuídos uniformemente entre as divisões do Spanner disponíveis. O comando atualizado para criar a tabela e o índice é semelhante a este:

CREATE TABLE Player (
        PlayerID STRING(36) NOT NULL,
        IndexPartition INT64 NOT NULL
        Attribute INT64 NOT NULL
) PRIMARY KEY (PlayerID)

CREATE INDEX idx_attribute ON Player(IndexPartition,Attribute)

A adição de uma coluna IndexPartition ao esquema distribui uniformemente os jogadores no lançamento.

O valor IndexPartition precisa ter um intervalo limitado para consultas eficientes, mas também ter um intervalo que seja pelo menos o dobro do número de divisões para uma distribuição eficiente.

Nesse caso, o estúdio atribuiu manualmente a cada jogador um IndexPartition entre 1 e 6 no aplicativo do jogo.

Métodos alternativos podem ser atribuir um número aleatório a cada jogador ou atribuir um valor derivado de um hash no valor PlayerID. Consulte O que os DBAs precisam saber sobre o Spanner, parte 1: chaves e índices para mais estratégias de fragmentação no nível do aplicativo.

A atualização da consulta anterior para usar esse índice aprimorado se parece com o seguinte:

SELECT PlayerID
        FROM Player@{force_index=idx_attribute}
        WHERE IndexPartition BETWEEN 1 and 6
        AND Attribute = 23
        LIMIT 10

Como nenhum teste Beta foi executado, o estúdio não percebeu que os testes tinham dados com suposições incorretas. Os testes de carga sintética são uma boa maneira de validar quantas consultas por segundo (QPS, na sigla em inglês) sua instância pode manipular, mas um teste Beta com jogadores reais é necessário para validar seu esquema e preparar um lançamento bem-sucedido.

Dimensionar o ambiente de produção para antecipar a demanda de pico

Geralmente, o pico de tráfego dos principais jogos ocorre no lançamento. A criação de um back-end escalonável não se aplica apenas aos serviços de plataforma e aos servidores de jogos dedicados, mas também aos bancos de dados. Com as soluções do Google Cloud, como o App Engine, é possível criar serviços de API de front-end que podem ser escalonados rapidamente. Ainda que o Spanner ofereça a flexibilidade de adicionar e remover nós on-line, ele não é um banco de dados de escalonamento automático. Você precisa provisionar nós suficientes para lidar com o pico de tráfego durante o lançamento.

Com base nos dados coletados durante o teste de carga ou em qualquer teste Beta público, é possível estimar o número de nós necessários para lidar com solicitações no lançamento. É recomendável adicionar alguns nós como buffer, caso você receba mais jogadores do que o esperado. Sempre dimensione o banco de dados de modo a não exceder um uso médio da CPU de 65%.

Aquecer o banco de dados antes do lançamento do jogo

Antes de lançar seu jogo, recomendamos que você aqueça seu banco de dados para aproveitar os recursos de carregamento em paralelo do Spanner. Para mais informações, consulte Como aquecer o banco de dados antes da inicialização do aplicativo.

Monitorar e entender o desempenho

Qualquer banco de dados de produção requer métricas abrangentes de monitoramento e desempenho. O Spanner vem com métricas integradas no Cloud Monitoring. Sempre que possível, recomendamos incorporar as bibliotecas de gRPC fornecidas ao seu processo de back-end do jogo porque elas incluem o rastreamento do OpenCensus (em inglês). O rastreamento do OpenCensus permite que você veja traces de consulta no Cloud Trace, bem como outras ferramentas de rastreamento de código aberto compatíveis.

No Cloud Monitoring, é possível ver detalhes sobre o uso do Spanner, incluindo armazenamento de dados e uso da CPU. Para a maioria dos casos, recomendamos que você baseie as decisões de escalonamento do Spanner nessa métrica de uso de CPU ou na latência observada. Para mais informações sobre o uso sugerido de CPU para desempenho otimizado, consulte Práticas recomendadas.

O Spanner oferece planos de execução de consulta. É possível analisar esses planos no console do Google Cloud e entrar em contato com o suporte se precisar de ajuda para entender o desempenho da sua consulta.

Ao avaliar o desempenho, mantenha os testes de ciclo curtos no mínimo porque o Spanner divide os dados de forma transparente nos bastidores para otimizar o desempenho com base nos padrões de acesso a dados. É preciso avaliar o desempenho usando cargas de consulta sustentadas e realistas.

Excluir linhas em vez de recriar tabelas ao remover dados

Quando você trabalha com o Spanner, as tabelas recém-criadas ainda não tiveram a oportunidade de passar por tamanho baseado em carga ou tamanho para melhorar o desempenho. Quando você exclui dados descartando uma tabela e recriando-a, o Spanner precisa de dados, consultas e tempo para determinar as divisões corretas da tabela. Se estiver planejando preencher novamente uma tabela com os mesmos tipos de dados (por exemplo, ao executar testes de desempenho consecutivos), poderá executar uma consulta DELETE nas linhas que contêm dados desnecessários. Pela mesma razão, as atualizações de esquema precisam usar a API Cloud Spanner fornecida e evitar uma estratégia manual, como criar uma nova tabela e copiar os dados de outra tabela ou um arquivo de backup.

Selecionar uma localidade de dados para atender aos requisitos de conformidade

Muitos jogos precisam cumprir as leis regionais de dados, como o GDPR, quando jogados em todo o mundo. Para ajudar a atender às suas necessidades do GDPR, consulte o artigo sobre o Google Cloud e o GDPR e selecione a configuração regional do Spanner correta.

A seguir