Best practice per l'utilizzo di Cloud Spanner come database per i videogiochi

Questo documento descrive le best practice per l'uso di Spanner come database di backend principale per l'archiviazione dello stato dei giochi. Puoi utilizzare Spanner al posto dei database comuni per archiviare i dati di autenticazione dei giocatori e i dati di inventario. Questo documento è destinato agli ingegneri del backend dei giochi che lavorano sull'archiviazione di stato a lungo termine, nonché agli operatori e agli amministratori di infrastruttura di gioco che supportano questi sistemi e sono interessati a ospitare il proprio database di backend su Google Cloud.

I giochi multiplayer e online si sono evoluti fino a richiedere strutture di database sempre più complesse per monitorare i diritti dei giocatori, lo stato e i dati di inventario. L'aumento della base di giocatori e l'aumento della complessità del gioco hanno portato a soluzioni di database complesse da scalare e gestire, che spesso richiedono l'utilizzo di sharding o clustering. Il monitoraggio di preziosi elementi in-game o dei progressi critici dei giocatori richiede in genere delle transazioni ed è difficile da risolvere in molti tipi di database distribuiti.

Spanner è il primo servizio di database scalabile di livello enterprise, distribuito a livello globale e a elevata coerenza, creato per il cloud allo scopo di combinare i vantaggi della struttura di un database relazionale con la scalabilità orizzontale non relazionale. Molte aziende di videogiochi si sono rivelate adatte a sostituire i database dello stato dei giochi e di autenticazione nei sistemi su scala di produzione. Puoi scalare per aumentare le prestazioni o l'archiviazione utilizzando la console Google Cloud per aggiungere nodi. Spanner è in grado di gestire in modo trasparente la replica globale con elevata coerenza, eliminando la necessità di gestire repliche a livello di regione.

Questo documento sulle best practice illustra quanto segue:

  • Concetti importanti di Spanner e differenze dai database comunemente utilizzati nei giochi.
  • Quando Spanner è il database giusto per il tuo gioco.
  • Pattern da evitare quando utilizzi Spanner per i giochi.
  • Progettare le operazioni del tuo database con Spanner come database del tuo gioco.
  • Modellare i dati e creare uno schema per ottenere le migliori prestazioni con Spanner.

Terminologia

Diritti
Giochi, espansioni o acquisti in-app appartenenti a un giocatore.
Informazioni di identificazione personale (PII)
Nei giochi, informazioni che in genere includono l'indirizzo email e i dati dell'account pagamenti, come il numero di carta di credito e l'indirizzo di fatturazione. In alcuni mercati, queste informazioni potrebbero includere un numero del documento di identità nazionale.
Database dei giochi (DB del gioco)
Un database che contiene i progressi dei giocatori e l'inventario di un gioco.
Database autenticazione (DB di autenticazione)
Un database che include i diritti dei giocatori e le PII che i giocatori utilizzano al momento di effettuare un acquisto. Il database di autenticazione è anche noto come database dell'account o database del player. Questo database a volte viene combinato con il database del gioco, ma spesso sono separati in studi o editori che hanno più titoli.
Transazione
Una transazione di database: un insieme di operazioni di scrittura che hanno un effetto "tutto o niente". La transazione ha esito positivo e tutti gli aggiornamenti hanno effetto oppure il database viene restituito a uno stato che non include nessuno degli aggiornamenti della transazione. Nei giochi, le transazioni dei database sono fondamentali per l'elaborazione dei pagamenti e per l'assegnazione della proprietà di una valuta o inventario in-game di valore.
Sistema di gestione di database relazionali (RDBMS)
Un sistema di database basato su tabelle e righe che fanno riferimento l'una all'altra. SQL Server, MySQL e (meno comunemente) Oracle® sono esempi di database relazionali utilizzati nei giochi. Vengono utilizzati di frequente perché possono fornire metodologie familiari e forti garanzie riguardo alle transazioni.
Database NoSQL (DB NoSQL)
Database non strutturati in modo relazionale. Questi database stanno diventando più popolari nei giochi perché offrono molta flessibilità quando il modello dei dati cambia. I database NoSQL includono MongoDB e Cassandra.
Chiave primaria
Di solito si tratta della colonna che contiene l'ID univoco per gli elementi dell'inventario, gli account giocatore e le transazioni di acquisto.
Istanza
Un unico database. Ad esempio, un cluster esegue più copie del software del database, ma viene visualizzato come singola istanza nel backend del gioco.
Nodo
Ai fini del presente documento, una singola macchina che esegue una copia del software del database.
Replica
Una seconda copia di un database. Le repliche vengono utilizzate di frequente per il recupero dei dati e l'alta disponibilità o per aumentare la velocità effettiva di lettura.
Cluster
Più copie del software in esecuzione su molte macchine che insieme vengono visualizzate come un'unica istanza nel backend del gioco. Il clustering viene utilizzato per garantire scalabilità e disponibilità.
Shard
Un'istanza di un database. Molti studi di gioco eseguono diverse istanze di database omogene, ciascuna delle quali contiene un sottoinsieme di dati di gioco. Ognuna di queste istanze è comunemente definita shard. In genere, il sharding viene eseguito per migliorare le prestazioni o la scalabilità, sacrificando l'efficienza di gestione e aumentando la complessità delle app. Lo sharding in Spanner viene implementato utilizzando i split.
Suddividi
Spanner suddivide i dati in blocchi chiamati split, in cui le singole suddivisioni possono spostarsi in modo indipendente l'una dall'altra e essere assegnate a server diversi. Una suddivisione è definita come un intervallo di righe in una tabella di primo livello (in altre parole senza interleaving), in cui le righe sono ordinate in base alla chiave primaria. Le chiavi di inizio e fine di questo intervallo sono chiamate "confini della suddivisione". Spanner aggiunge e rimuove automaticamente i confini della suddivisione, che modificano il numero di suddivisioni nel database. Spanner suddivide i dati in base al carico: aggiunge automaticamente confini della suddivisione quando rileva un carico elevato in lettura o scrittura distribuito tra più chiavi in una suddivisione.
Hotspot
Quando una singola suddivisione in un database distribuito come Spanner contiene record che ricevono una grande parte di tutte le query inviate al database. Questo scenario è indesiderato perché influisce negativamente sulle prestazioni.

Utilizzo di Spanner per i giochi

Nella maggior parte dei casi in cui si prende in considerazione un RDBMS per il proprio gioco, Spanner è una scelta appropriata perché può sostituire efficacemente il DB di gioco, il DB di autenticazione o, in molti casi, entrambi.

Database di gioco

Spanner può operare come un'unica autorità transazionale a livello mondiale, il che lo rende ideale per i sistemi di inventario dei giochi. Qualsiasi valuta o articolo in-game che può essere scambiato, venduto, regalato o altrimenti trasferito da un giocatore all'altro rappresenta una sfida nei backend di gioco su larga scala. Spesso, la popolarità di un gioco può superare la capacità di un database tradizionale di gestire tutto in un database di un singolo nodo. A seconda del tipo di gioco, il database può avere difficoltà con il numero di operazioni necessarie per gestire il carico del player e la quantità di dati archiviati. Questo spesso porta gli sviluppatori di giochi a suddividere il database per prestazioni aggiuntive o ad archiviare tabelle con dimensioni sempre maggiori. Questa soluzione comporta complessità operativa e costi di manutenzione elevati.

Per ridurre questa complessità, una strategia comune prevede l'esecuzione di regioni di gioco completamente separate senza la possibilità di spostare i dati da una all'altra. In questo caso, gli articoli e la valuta non possono essere scambiati tra giocatori in regioni di gioco diverse, poiché gli inventari in ogni regione sono segregati in database distinti. Tuttavia, questa configurazione sacrifica l'esperienza preferita del player, a favore dello sviluppatore e della semplicità operativa.

D'altra parte, puoi consentire le compravendita tra regioni in un database con restrizioni geografiche, ma spesso con costi elevati di complessità. Questa configurazione richiede che le transazioni avvengano su più istanze di database, generando una logica lato applicazione complessa e soggetta a errori. Cercare di bloccare le transazioni su più database può avere impatti significativi sulle prestazioni. Inoltre, il fatto di non poter fare affidamento sulle transazioni atomiche può portare a exploit per i giocatori, come la valuta in-game o la duplicazione degli articoli, che danneggiano l'ecosistema e la community del gioco.

Spanner semplifica l'approccio alle transazioni su inventario e valuta. Anche quando utilizzi Spanner per archiviare tutti i tuoi dati di gioco in tutto il mondo, offre transazioni di lettura-scrittura con proprietà più efficaci rispetto a quelle di atomicità, coerenza, isolamento e durabilità (ACID) tradizionali. Con la scalabilità di Spanner, i dati non devono essere segmentati in istanze di database separate quando sono necessarie più prestazioni o spazio di archiviazione; basta aggiungere più nodi. Inoltre, l'alta disponibilità e la resilienza dei dati con cui i giochi spesso clusterano i database vengono gestite in modo trasparente da Spanner, senza bisogno di configurazioni o gestione aggiuntive.

DB di autenticazione

I Auth DB possono essere gestiti anche da Spanner, soprattutto se vuoi standardizzare su un singolo RDBMS a livello di studio o publisher. Sebbene i database di autenticazione per i giochi spesso non richiedano la scalabilità di Spanner, le garanzie transazionali e l'alta disponibilità dei dati possono renderlo convincente. La replica dei dati in Spanner è trasparente, sincrona e integrata. Spanner ha configurazioni che offrono 99,99% ("quattro nove") o il 99,999% ("cinque nove") di disponibilità, con "cinque nove" corrispondenti a meno di cinque minuti e mezzo di indisponibilità in un anno. Questo tipo di disponibilità lo rende un'ottima scelta per il percorso di autenticazione critico richiesto all'inizio di ogni sessione giocatore.

best practice

Questa sezione fornisce suggerimenti su come utilizzare Spanner nella progettazione di giochi. È importante modellare i dati di gioco in modo che usufruiscano delle funzionalità uniche offerte da Spanner. Sebbene sia possibile accedere a Spanner utilizzando la semantica del database relazionale, alcuni punti di progettazione dello schema possono aiutarti ad aumentare le prestazioni. La documentazione di Spanner contiene suggerimenti dettagliati per la progettazione degli schemi che puoi consultare, ma le sezioni seguenti sono alcune best practice per i database di gioco.

Le pratiche riportate in questo documento si basano sulle esperienze relative all'utilizzo da parte dei clienti e ai case study.

Usa gli UUID come ID giocatore e carattere

La tabella dei giocatori presenta in genere una riga per ogni giocatore e include la valuta in-game, i progressi o altri dati che non possono essere mappati facilmente a righe della tabella di inventario discreta. Se il tuo gioco consente ai giocatori di avere progressi salvati separati per più personaggi, ad esempio molti grandi giochi multiplayer persistenti di grandi dimensioni, in genere questa tabella contiene invece una riga per ogni personaggio. Il pattern è altrimenti lo stesso.

Ti consigliamo di utilizzare un carattere univoco globale o un identificatore di player (ID carattere) come chiave primaria della tabella dei caratteri. Ti consigliamo inoltre di utilizzare l'identificatore univoco universale (UUID) v4, perché distribuisce i dati del player tra i nodi DB e può aiutarti a ottenere maggiori prestazioni da Spanner.

Utilizzare l'interleaving per le tabelle dell'inventario

La tabella dell'inventario contiene spesso elementi in-game, come equipaggiamento dei personaggi, carte o unità. Generalmente, un singolo giocatore ha molti oggetti nel proprio inventario. Ogni elemento è rappresentato da una singola riga nella tabella.

Analogamente ad altri database relazionali, una tabella dell'inventario in Spanner ha una chiave primaria che rappresenta un identificatore univoco globale per l'elemento, come illustrato nella tabella seguente.

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

Nella tabella dell'inventario di esempio, i valori itemID e playerID vengono troncati per la leggibilità. Una tabella di inventario effettiva contiene anche molte altre colonne non incluse nell'esempio.

Un approccio tipico in un RDBMS per monitorare la proprietà degli elementi consiste nell'utilizzare una colonna come chiave esterna contenente l'ID player dell'attuale proprietario. Questa colonna è la chiave primaria di una tabella di database separata. In Spanner, puoi utilizzare l'interleaving, che memorizza le righe dell'inventario vicino alla riga della tabella del player associata per migliorare il rendimento. Quando utilizzi tabelle con interleaving, tieni presente quanto segue:

  • Devi mantenere i dati totali nella riga del player e in tutte le righe dell'inventario discendenti al di sotto di circa 4 GiB. Questa limitazione di solito non è un problema relativo alla progettazione di un modello dei dati appropriato.
  • Non puoi generare un oggetto senza un proprietario. Puoi evitare gli oggetti senza proprietario nel design del gioco, a patto che la limitazione sia nota in anticipo.

Progetta l'indicizzazione in modo da evitare gli hotspot

Molti sviluppatori di giochi implementano gli indici in molti campi dell'inventario per ottimizzare determinate query. In Spanner, la creazione o l'aggiornamento di una riga con dati in quell'indice genera un carico di scrittura aggiuntivo proporzionale al numero di colonne indicizzate. Puoi migliorare le prestazioni di Spanner eliminando gli indici non utilizzati di frequente o implementando questi indici in altri modi che non influiscono sulle prestazioni del database.

Nell'esempio seguente, c'è una tabella per i record di punteggi più alti dei giocatori a lungo termine:

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

Questa tabella contiene l'ID giocatore (UUIDv4), un numero che rappresenta una modalità di gioco, una fase o una stagione e il punteggio del giocatore.

Per velocizzare le query che filtrano i dati in base alla modalità di gioco, considera il seguente indice:

CREATE INDEX idx_score_ranking ON Ranking (
        GameMode,
        Score DESC
)

Se tutti usano la stessa modalità di gioco chiamata 1, questo indice crea un hotspot in cui GameMode=1. Se vuoi ottenere un ranking per questa modalità di gioco, l'indice analizza soltanto le righe che contengono GameMode=1, restituendo rapidamente il ranking.

Se modifichi l'ordine dell'indice precedente, puoi risolvere questo problema relativo a un hotspot:

CREATE INDEX idx_score_ranking ON Ranking (
        Score DESC,
        GameMode
)

Questo indice non creerà un hotspot significativo per i giocatori che gareggiano nella stessa modalità di gioco, a condizione che i loro punteggi siano distribuiti nell'intervallo possibile. Tuttavia, la generazione dei punteggi non sarà così rapida come con l'indice precedente, perché la query analizza tutti i punteggi di tutte le modalità per determinare se GameMode=1.

Di conseguenza, l'indice riordinato risolve l'hotspot precedente nella modalità di gioco, ma ha comunque margini di miglioramento, come illustrato nel seguente design.

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

CREATE INDEX idx_score_ranking ON Ranking (
        Score DESC
)

Ti consigliamo di spostare la modalità di gioco fuori dallo schema della tabella e di utilizzare una tabella per modalità, se possibile. Utilizzando questo metodo, quando recuperi i punteggi per una modalità, esegui solo una query su una tabella con i punteggi per quella modalità. Questa tabella può essere indicizzata in base al punteggio per recuperare rapidamente gli intervalli di punteggi senza un pericolo significativo di hotspot (a condizione che i punteggi siano ben distribuiti). Al momento della stesura di questo documento, il numero massimo di tabelle per database in Spanner è 2560, più che sufficiente per la maggior parte dei giochi.

Database separati per tenant

A differenza di altri carichi di lavoro, per cui consigliamo di progettare per la multitenancy in Spanner utilizzando coppie chiave-valore primarie diverse per i dati di gioco, consigliamo l'approccio più convenzionale di database separati per tenant. Le modifiche allo schema sono comuni con il rilascio di nuove funzionalità dei giochi nei giochi di servizio in tempo reale e l'isolamento dei tenant a livello di database può semplificare gli aggiornamenti dello schema. Questa strategia può anche ottimizzare il tempo necessario per il backup o il ripristino dei dati di un tenant, perché queste operazioni vengono eseguite contemporaneamente su un intero database.

Evita aggiornamenti incrementali dello schema

Diversamente da alcuni database relazionali convenzionali, Spanner rimane operativo durante gli aggiornamenti dello schema. Tutte le query relative allo schema precedente vengono restituite (anche se potrebbero essere restituite meno rapidamente del solito) e le query sul nuovo schema vengono restituite non appena diventano disponibili. Puoi progettare il processo di aggiornamento in modo che il gioco resti in esecuzione durante gli aggiornamenti dello schema durante l'esecuzione su Spanner, a condizione di tenere a mente i vincoli precedenti.

Tuttavia, se richiedi un'altra modifica dello schema mentre ne è in corso l'elaborazione, il nuovo aggiornamento viene messo in coda e non verrà eseguito fino al completamento di tutti i precedenti aggiornamenti dello schema. Puoi evitare questa situazione pianificando aggiornamenti dello schema di grandi dimensioni, anziché emettere molti aggiornamenti incrementali dello schema in un breve periodo. Per ulteriori informazioni sugli aggiornamenti dello schema, incluso come eseguire un aggiornamento dello schema che richiede la convalida dei dati, consulta la documentazione sull'aggiornamento dello schema di Spanner

Considera l'accesso e le dimensioni del database

Quando sviluppi il tuo server di gioco e i servizi della piattaforma per utilizzare Spanner, considera le modalità di accesso del gioco al database e le dimensioni del database per evitare costi inutili.

Usa librerie e driver nativi

Quando sviluppi con Spanner, valuta in che modo il tuo codice si interfaccia con il database. Spanner offre librerie client native per molti dei linguaggi più comuni, che in genere sono ricchi di funzionalità e ad alte prestazioni. Sono disponibili anche i driver JDBC che supportano le istruzioni DML (Data Manipulation Language) e DDL (Data Manipulation Language). Nei casi in cui Spanner viene utilizzato in un nuovo sviluppo, consigliamo di utilizzare le librerie client di Cloud per Spanner. Sebbene le tipiche integrazioni dei motori di gioco non offrano molta flessibilità nella selezione del linguaggio, per i servizi di piattaforma che accedono a Spanner, esistono casi di clienti di videogiochi che utilizzano Java o Go. Per le applicazioni a velocità effettiva elevata, seleziona una libreria in cui puoi utilizzare lo stesso client Spanner per più richieste sequenziali.

Ridimensiona il database in base alle esigenze di test e produzione

Durante lo sviluppo, un'istanza di Spanner a nodo singolo è probabilmente sufficiente per la maggior parte delle attività, inclusi i test funzionali.

Valuta le esigenze di Spanner per la produzione

Quando passi dallo sviluppo al test e poi alla produzione, è importante rivalutare le esigenze di Spanner per assicurarti che il tuo gioco sia in grado di gestire il traffico dei giocatori in tempo reale.

Prima di passare alla produzione, i test di caricamento sono fondamentali per verificare che il backend sia in grado di gestire il carico durante la produzione. Ti consigliamo di eseguire test di carico con il doppio del carico previsto in produzione, in modo da prepararti ai picchi di utilizzo e ai casi in cui il tuo gioco è più popolare del previsto.

Esegui test di carico utilizzando dati reali

Non è sufficiente eseguire un test di carico con dati sintetici. Devi inoltre eseguire i test di carico utilizzando pattern di dati e di accesso il più vicino possibile a quanto previsto in produzione. I dati sintetici potrebbero non rilevare potenziali hotspot nella progettazione dello schema Spanner. Non c'è niente di meglio che eseguire un beta test (aperto o chiuso) con player reali per verificare il comportamento di Spanner con dati reali.

Il seguente diagramma è uno schema di esempio della tabella del player di uno studio di videogiochi che illustra l'importanza dell'utilizzo di beta test per il test di carico.

Elenco dei nomi dei player e un attributo per il test di carico.

Lo studio ha preparato i dati sulla base delle tendenze relative a un gioco precedente, gestito da un paio d'anni. L'azienda si aspettava che lo schema rappresentasse ben i dati di questo nuovo gioco.

A ogni record sono associati alcuni attributi numerici che consentono di tenere traccia dei progressi del giocatore nel gioco (come ranking e tempo di gioco). Per l'attributo di esempio utilizzato nella tabella precedente, ai nuovi giocatori viene assegnato un valore iniziale pari a 50, che diventa poi compreso tra 1 e 100 man mano che il player avanza.

Lo studio vuole indicizzare questo attributo per velocizzare le query importanti durante il gameplay.

In base a questi dati, lo studio ha creato la seguente tabella Spanner, con una chiave primaria che utilizza PlayerID e un indice secondario su Attribute.

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

CREATE INDEX idx_attribute ON Player(Attribute)

È stata eseguita una query sull'indice per trovare fino a dieci giocatori con Attribute=23, in questo modo:

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

In base alla documentazione sull'ottimizzazione della progettazione dello schema, Spanner archivia i dati degli indici nello stesso modo delle tabelle, con una riga per voce di indice. Nei test di carico, questo modello svolge un lavoro accettabile nella distribuzione del carico di lettura e scrittura dell'indice secondario in più suddivisioni di Spanner, come illustrato nel seguente diagramma:

Giocatori distribuiti tra le suddivisioni di Spanner in base al loro attributo.

Sebbene i dati sintetici utilizzati nel test di carico siano simili allo stato stazionario finale del gioco, in cui i valori Attribute sono ben distribuiti, il design del gioco impone che tutti i giocatori inizino con Attribute=50. Poiché ogni nuovo giocatore inizia con Attribute=50, quando nuovi giocatori si uniscono, vengono inseriti nella stessa parte dell'indice secondario idx_attribute. Ciò significa che gli aggiornamenti vengono indirizzati alla stessa suddivisione di Spanner, causando un hotspot durante la finestra di avvio del gioco. Questo è un uso inefficiente di Spanner.

Giocatori al momento del lancio con lo stesso attributo che creano un hotspot in un singolo segmento Spanner.

Nel diagramma seguente, l'aggiunta di una colonna IndexPartition allo schema dopo il lancio risolve il problema dell'hotspot e i player vengono distribuiti uniformemente tra le suddivisioni di Spanner disponibili. Il comando aggiornato per la creazione della tabella e dell'indice è simile al seguente:

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)

L'aggiunta di una colonna IndexPartition allo schema consente di distribuire in modo uniforme i giocatori al momento del lancio.

Il valore IndexPartition deve avere un intervallo limitato per eseguire query efficienti, ma deve anche avere un intervallo almeno doppio del numero di suddivisioni per una distribuzione efficiente.

In questo caso, lo studio ha assegnato manualmente a ogni giocatore un IndexPartition compreso tra 1 e 6 nell'applicazione del gioco.

Alcuni metodi alternativi potrebbero essere l'assegnazione di un numero casuale a ogni player o l'assegnazione di un valore derivato da un hash sul valore PlayerID. Consulta Cosa devono sapere i DBA su Spanner, parte 1: Chiavi e indici per altre strategie di sharding a livello di applicazione.

L'aggiornamento della query precedente per utilizzare questo indice migliorato sarà simile al seguente:

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

Poiché non è stato eseguito alcun beta test, lo studio non si è accorto di eseguire il test utilizzando dati con ipotesi errate. Sebbene i test di carico sintetici siano un buon modo per convalidare il numero di query al secondo (QPS) che l'istanza è in grado di gestire, è necessario un beta test con player reali per convalidare lo schema e preparare un lancio riuscito.

Ridimensionare l'ambiente di produzione per anticipare il picco della domanda

I giochi più importanti spesso registrano il picco del traffico al momento del lancio. La creazione di un backend scalabile si applica non solo ai servizi di piattaforma e ai server di gioco dedicati, ma anche ai database. Utilizzando soluzioni Google Cloud come App Engine, puoi creare servizi API frontend in grado di fare lo scale up rapidamente. Anche se Spanner offre la flessibilità di aggiungere e rimuovere nodi online, non è un database a scalabilità automatica. Devi eseguire il provisioning di un numero sufficiente di nodi per gestire il picco di traffico all'avvio.

In base ai dati raccolti durante i test di carico o di beta test pubblici, puoi stimare il numero di nodi necessari per gestire le richieste al momento dell'avvio. È buona norma aggiungere alcuni nodi come buffer nel caso in cui il numero di player sia maggiore del previsto. Devi sempre dimensionare il database in base a non superare l'utilizzo medio della CPU del 65%.

Riscalda il database prima del lancio del gioco

Prima di lanciare il gioco, ti consigliamo di riavviare il database per sfruttare le funzionalità di caricamento in contemporanea di Spanner. Per ulteriori informazioni, consulta Riscaldamento del database prima dell'avvio dell'applicazione.

Monitorare e comprendere il rendimento

Qualsiasi database di produzione richiede metriche complete di monitoraggio e prestazioni. Spanner include metriche integrate in Cloud Monitoring. Se possibile, consigliamo di incorporare le librerie gRPC fornite nel processo di backend del gioco, poiché queste librerie includono il tracciamento di OpenCensus. Il tracciamento di OpenCensus consente di visualizzare le tracce delle query in Cloud Trace e altri strumenti di tracciamento open source supportati.

In Cloud Monitoring puoi visualizzare i dettagli relativi all'utilizzo di Spanner, tra cui l'archiviazione dei dati e l'utilizzo della CPU. Nella maggior parte dei casi, consigliamo di basare le decisioni di scalabilità di Spanner su questa metrica di utilizzo della CPU o sulla latenza osservata. Per ulteriori informazioni sull'utilizzo suggerito della CPU per ottimizzare le prestazioni, consulta le best practice.

Spanner offre piani di esecuzione delle query. Puoi esaminare questi piani nella console Google Cloud e contattare l'assistenza se hai bisogno di aiuto per comprendere le prestazioni delle query.

Quando valuti le prestazioni, riduci al minimo i test dei cicli brevi, poiché Spanner suddivide in modo trasparente i dati dietro le quinte per ottimizzare le prestazioni in base ai pattern di accesso ai dati. Dovresti valutare le prestazioni utilizzando caricamenti di query realistici e sostenuti.

Quando rimuovi i dati, elimina le righe anziché ricreare le tabelle

Quando lavori con Spanner, le tabelle appena create non hanno ancora avuto l'opportunità di essere sottoposte alla suddivisione in base al carico o alle dimensioni per migliorare le prestazioni. Quando elimini i dati eliminando una tabella e ricreandola, Spanner ha bisogno di dati, query e tempo per determinare le suddivisioni corrette per la tabella. Se prevedi di ricompilare una tabella con lo stesso tipo di dati (ad esempio, durante l'esecuzione di test delle prestazioni consecutivi), puoi eseguire una query DELETE sulle righe contenenti dati che non ti servono più. Per lo stesso motivo, gli aggiornamenti dello schema devono utilizzare l'API Cloud Spanner fornita e devono evitare una strategia manuale, come la creazione di una nuova tabella e la copia dei dati da un'altra tabella o da un file di backup.

Seleziona una località dei dati per soddisfare i requisiti di conformità

Quando vengono giocati in tutto il mondo, molti giochi devono rispettare le leggi sulla località dei dati, come il GDPR. Per supportare le tue esigenze relative al GDPR, consulta il white paper su Google Cloud e il GDPR e seleziona la configurazione regionale di Spanner corretta.

Passaggi successivi