In che modo mmorpg memorizza i dati?


22

Voglio usare il database sql nel mio server.exe.

diciamo che 1000 utenti online. E i giocatori cambieranno i loro dati quando giocano. E il server deve salvare questi aggiornamenti.

Ma come ?

penso che ci siano due modi:

1) il server salverà in ram in fase di esecuzione e a volte o ogni ora il server scriverà i dati (aggiornamento) nel database sql da ram. Ma se l'elettricità si spegne o in qualche modo il server si spegne, gli aggiornamenti non verranno salvati. ovviamente non voglio perdere gli aggiornamenti.

2) il server salverà gli aggiornamenti nel database in fase di esecuzione. ma cosa accadrà per accelerare? Ho pensato a un metodo. ti mostrerò di seguito con l'immagine. Posso ottenere abbastanza velocità per 1000 giocatori online con questo metodo? inserisci qui la descrizione dell'immagine


11
Hai fatto dei benchmark? Cosa ti fa pensare che le operazioni del database siano un problema per il tuo gioco?
congusbongus,

3
Se il tuo stato di gioco è effettivamente relazionale? Sei sicuro di voler un database SQL?
Smetti di fare del male a Monica il

6
Leggi anche come gestire le password usando gli hash. O almeno avvisare l'utente che la loro password viene salvata come testo normale, quindi sono consapevoli di non utilizzare un'altra password sicura.
TomTsagk il

24
Come nota a margine, se vuoi costruire un MMO commerciale e stai ponendo domande come questa, probabilmente dovresti iniziare con qualcosa di più piccolo. Gli MMO sono incredibilmente difficili da fare, figuriamoci nel farli nel modo giusto, e non sono poi così fantastici dal punto di vista commerciale. Se questa è solo una cosa personale e vuoi aumentare il numero di giocatori, inizia con qualcosa come 64 giocatori, quindi sali su. Sarà molto più facile che provare a progettare da zero l'architettura "perfetta" senza esperienza. Vedere questo .
Finanzi la causa di Monica il

1
È possibile scrivere un'API generale indipendente dallo storage. Quindi scrivere un adattatore che memorizza nella cache i dati nella RAM per l'archiviazione ritardata. Oppure è possibile scrivere un adattatore che memorizza nella cache i dati in un file temporaneo prima di scaricarli nel database SQL. In questo modo è possibile attivare e disattivare la memorizzazione nella cache per scoprire qual è la migliore. Non è necessario scrivere troppo codice musch extra, se la tua architettura è costruita nel modo giusto.
0xC0DEGURU

Risposte:


37

La maggior parte degli MMO (o progetti che usano un'architettura simile) su cui ho lavorato o conosco l'uso del primo metodo: i server di gioco funzionano principalmente con la RAM sui computer che eseguono i processi del server e serializzano periodicamente solo i dati di gioco rilevanti su un database SQL per l'archiviazione (se ne viene usato uno).

I problemi che noti in caso di interruzione di corrente sono validi, ma meno probabili di problemi come arresti anomali nel processo (l'affidabilità dei tempi di attività è generalmente una delle cose per le quali pagheresti il ​​datacenter). Ma ancora. Puoi mitigare questi problemi attraverso cose come l'ottimizzazione dell'intervallo di salvataggio (quindi un errore costa solo pochi minuti di avanzamento), la distribuzione delle code di salvataggio su più macchine, l'ambito aggressivo della quantità di dati che devono essere salvati e l'implementazione del salvataggio riavviabile code.

In generale, l'utilizzo dello stesso server SQL come memoria principale sarà spiacevolmente lento (e ingombrante). Non vedo abbastanza dettagli nella tua proposta lì da poter dire con certezza se funzionerebbe solo per circa 1000 giocatori - probabilmente andrebbe bene. Ma non credo che tu possa renderlo aggressivamente scalabile.

Inoltre, non risolve il problema. Un'interruzione di corrente durante il processo di salvataggio perderà o danneggerà i dati a meno che non si esegua il lavoro per implementare lo stesso tipo di coda di salvataggio riavviabile (che anche in quel caso, che riduce solo gravemente la probabilità di una catastrofica perdita di dati, non lo impedisce) .

Ti consiglierei di andare con il primo approccio.


10
Per quanto riguarda "ottimizzare l'intervallo di salvataggio", l'ultimo MMO su cui ho lavorato ha avuto un intervallo di salvataggio in base al numero di giocatori attivi. Sapevamo che sarebbe stato in grado di gestire il salvataggio dei dati di X giocatori al secondo senza che si notasse un collo di bottiglia, quindi abbiamo avuto un risparmio di poco inferiore a X giocatori al secondo su base rotante. Di solito finiva per essere un salvataggio per ogni giocatore ogni due minuti circa nei giorni di grande affluenza, e forse due volte al minuto durante i tempi lenti.
Meanbits

4
La "coda di salvataggio riavviabile" suona come un diario, come implementato da molti filesystem e motori di database?
gravità

6
Questi problemi non sono univoci per MMO, o anche videogiochi, a tutti . Quasi tutti gli ORM esistenti forniscono una sorta di meccanismo di memorizzazione nella cache / batch. Non è necessario creare la tua soluzione.
BlueRaja - Danny Pflughoeft il

3
Se finisci con il salvare su un disco ad un certo intervallo, ti consiglio di progettare un sistema in cui le cose possano essere salvate immediatamente, per quando le persone ottengono un raro drop / die / etc. In questo modo, se si verifica un arresto anomalo del server o qualcosa del genere, le persone che hanno realizzato qualcosa di grosso non saranno troppo turbate.
Jon

5
@Jon, e poi ti imbatti nel problema delle persone che riescono a duplicare gli oggetti. Idealmente, si salva periodicamente l'intero stato del gioco come una singola transazione. Una volta che inizi a salvare a pezzi, ti ritrovi con situazioni in cui un arresto anomalo può causare dati incoerenti; i giocatori che possono innescare un crash su richiesta o addirittura prevedere quando è probabile che si verifichi un crash, possono sfruttare questo a proprio vantaggio.
Segna il

15

1000 giocatori possono o meno essere un problema. Dipende dalla frequenza con cui è necessario aggiornare il database. Tuttavia esiste una soluzione semplice: mettere il database sul proprio server.


Ho dato una sbirciatina a come il sistema di database funziona un gioco che la gente chiamerebbe MMO-Lite - che non rivelerò - ma posso dire che ha costantemente più di 1000 giocatori, questo è l'abstract:

  • Usano un database "No-SQL" basato su documenti per informazioni sui personaggi privati ​​(inventario, equipaggiamento, simili).
  • Usano un database relazionale più tradizionale per le informazioni sui personaggi pubblici che vengono aggiornate raramente (nome, risultati, ecc ...) e statistiche.

L'utilizzo di un database basato su documenti risulta essere una buona idea per le prestazioni in questo caso. È buono per accedere ai dati, anche se è male per fare join e aggregazioni ... ma non lo faranno con i dati che ci sono.

D'altra parte, quando hanno bisogno di fare qualcosa come cambiare un oggetto con un altro oggetto per tutti, la necessità di eseguire uno script di sfondo che diventi carattere per carattere e li aggiorni uno per uno, ci vuole tempo notevole.


I dati del personaggio esistono sia sul client che sul server e il sistema è progettato per mantenerli sincronizzati, facendo le stesse operazioni su entrambi i lati.

Ora, quando un giocatore fa una transazione con il sistema - diciamo scambiare un oggetto con un altro tramite NPC o simili - questo ha queste fasi:

  • Il client verifica se l'operazione è valida
  • Il client invia l'operazione al server (operazione asincrona)
  • Il client aggiorna il suo modello in RAM
  • Il server verifica se l'operazione è valida
  • Il server aggiorna il suo modello in RAM
  • Il server aggiorna il database (operazione asincrona)
  • Il server comunica al client che la modifica è avvenuta

Note :

  • Gli aggiornamenti del database, sebbene asincroni, vengono eseguiti immediatamente. Se per qualsiasi motivo il server di gioco non funziona, non si perde molto.
  • Il degrado delle prestazioni non è un grosso problema grazie al posizionamento dei database sui propri server.

Gli scambi tra i giocatori sono gestiti in modo simile, con regole extra per impedire ai giocatori di truffare altri giocatori e un'ulteriore tracciabilità nel caso in cui una transazione debba essere annullata. Ho sentito che ci sono registri speciali di tutte le transazioni che vengono conservati per un po 'di tempo (per risolvere i problemi quando qualcuno si lamenta), non so più come funziona quella parte.


A volte qualcosa va storto, questo ha due possibili esiti:

  • Se l'errore si verifica immediatamente, il server dirà al client, che ripristinerà l'operazione (il giocatore vede l'operazione annullata).
  • L'interfaccia utente dice che il giocatore ha un oggetto, ma il server non è d'accordo. Se l'utente tenta di utilizzarlo, chiederà al server di fallire, rendendo inutilizzabile l'oggetto falso. Il falso oggetto scompare quando viene ricaricato l'inventario, che viene utilizzato come opportunità per sincronizzare il modello.

In entrambi i casi, il client è a conoscenza dell'errore e lo registrerà insieme a tutto ciò che il giocatore stava facendo. La registrazione del lato client avviene continuamente. Quindi, al logout, se si è verificato un errore, il client invia i log al server.


Questo gioco non utilizza i tradizionali tempi di fermo giornalieri o settimanali della maggior parte degli MMORPG. Tale manutenzione programmata viene spesso utilizzata per azzerare contatori, timer, eseguire procedure di database. Sono anche l'opportunità di scambiare le versioni del server con un aggiornamento.


Grazie, ma per quanto riguarda i movimenti dei giocatori, ad esempio, se un giocatore si sposta dalla sua posizione attuale: x:10,y:10,z:10A x:11,y:11,z:11, questo dovrebbe essere salvato immediatamente nel database? cosa succede se il giocatore continua a correre, questo significa che salviamo la sua posizione attuale ogni 1 secondo o meno, e se ci sono migliaia di giocatori, si tratta di milioni di query al DB ogni secondo. È così che funziona ?
dwix,

2
La posizione del giocatore dovrebbe essere salvata molto raramente nel database. Lo vorresti solo in occasioni speciali come aprire il menu, accendere un falò, riposare ecc. A seconda del gioco non verrà nemmeno salvato così dettagliatamente. Alcuni giochi ti fanno sempre spawnare nella città più vicina, ecc., In modo da salvare la seccatura di salvare anche la posizione. Ma questo si sposta in base all'opinione.
Nico,

1
@dwix nel caso del gioco di cui parlo, la posizione del giocatore non viene nemmeno salvata. Se ti disconnetti e accedi, o se il server non funziona, il giocatore verrà riportato in una posizione sicura (modifica: è un'istanza privata, "casa" se vuoi, ma è uguale per tutti). Tuttavia, alcuni giochi mantengono la posizione esatta del giocatore, anche attraverso disconnessioni accidentali. Per fare ciò, il solito approccio è memorizzare tali informazioni con minore frequenza. Indipendentemente da ciò, non si fa ciò che il server attende sul database.
Theraot,

1
@dwix quando parli della posizione dell'avatar, non ti importa davvero dei valori storici, vero? Bene, se il database è un collo di bottiglia, quindi limitare i dati. Invece di archiviare ogni segno di spunta del server, archiviare meno frequentemente. Significa che il database non avrà il valore più aggiornato, ma non avrà un impatto così pesante sulle prestazioni. Nel frattempo il server manterrà comunque il valore di aggiornamento nella RAM, ed è quello con cui funziona. Addendum: onestamente consiglierei di non memorizzare le posizioni, ma alcuni giochi lo fanno.
Theraot,


7

Entrambi gli approcci sono utilizzati con MMORPG. Tenere tutto in memoria e controllare periodicamente il puntamento su disco sembra essere l'opzione più popolare, almeno per i giochi più vecchi. Ha il vantaggio di essere abbastanza semplice da implementare e ridimensionare abbastanza bene, ma renderlo affidabile dipende completamente dallo sviluppatore. I database SQL forniscono proprietà ACID che semplificano l'affidabilità, ma sono nel complesso più complicate da implementare bene e possono avere problemi con il ridimensionamento.

EVE Online è un esempio di MMO in cui tutto è archiviato in un database SQL. Penso che abbia raggiunto il picco a circa 60.000 utenti simultanei e ha dovuto dedicare un po 'di hardware costoso ai server di database nel corso degli anni per tenere il passo con il carico. Tuttavia EVE memorizza molti più dati per utente rispetto alla maggior parte dei MMORPG e ha transazioni molto più frequenti e varie. Le proprietà ACID del database consentono di mantenere l'intero database enorme e complicato in uno stato coerente.

Ad esempio, considera il caso in cui qualcuno consegna un oggetto a un altro giocatore. Il database di EVE garantisce che, anche in caso di crash o mancanza di corrente, l'oggetto finisce nell'inventario di un solo giocatore. Cioè, la transazione del database che rimuove l'oggetto dall'inventario di un giocatore e lo aggiunge a quello dell'altro giocatore è atomica. La transazione viene completata completamente o non si verifica affatto. Non puoi finire in uno stato in cui l'oggetto esiste nell'inventario dei giocatori o in entrambi.

Un MMORPG che mantiene in memoria i dati dei giocatori e controlla periodicamente i punti di controllo che deve implementare questa atomicità stessa. Un modo per farlo sarebbe il checkpoint dei dati di ogni giocatore allo stesso tempo, assicurando che il nuovo checkpoint sia completamente impegnato sul disco prima che sia considerato il checkpoint più recente. Il gioco dovrebbe anche garantire che i dati dei giocatori non possano cambiare mentre vengono controllati. Con un gran numero di giocatori attivi, la sfida diventa fare tutto questo senza causare un ritardo abbastanza lungo da essere notato dai giocatori.

Non sottovalutare l'importanza della coerenza. Quando sviluppi il tuo gioco, si bloccherà molto. Non è necessario rintracciare il motivo per cui gli oggetti stanno scomparendo e / o duplicando, non quando il problema è che un bug non correlato sta causando il blocco del gioco in un brutto momento. Inoltre, quando il tuo gioco sarà attivo, si bloccherà molto più di quanto ti aspetti. Il tuo server che stava funzionando perfettamente in fase di test, improvvisamente esporrà numerosi bug a pieno carico e i giocatori faranno cose che non ti aspettavi.

Nota che la maggior parte dei MMORPG utilizza database SQL per le informazioni relative all'account anche se non per i dati di gioco effettivi. Ancora più importante che mantenere lo stato di gioco in stato coerente è mantenere coerente lo stato di fatturazione. Il caso peggiore per la corruzione del database di gioco è che è necessario ripristinare il database da un backup giornaliero. Il peggior caso per corrompere il database degli account è che si va in bancarotta a causa di tutti gli storni di addebito.

Per il tuo progetto puoi probabilmente andare in entrambi i modi. Avere 1000 utenti simultanei probabilmente non supererà i limiti di ciò che un server SQL è in grado di gestire su un PC di merce in questi giorni, ma molto dipenderà dalla natura delle transazioni. Se hai familiarità con SQL e la progettazione di database relazionali, questo può funzionare per te. Ti consigliamo di ridurre al minimo le transazioni il più possibile, per qualcosa come gli hitpoint attuali del giocatore potresti volerli salvare periodicamente nel database poiché statistiche come queste non devono necessariamente essere coerenti. (Nel gioco PvP potrebbero però ...) Non archiviare affatto cose come mostri HP nel database, nella maggior parte dei giochi sono persistenti solo i dati relativi ai giocatori.

D'altra parte, se non sei un mago SQL, potresti trovare che mantenere tutti i dati in memoria molto più semplici per funzionare in modo affidabile. I database SQL semplificano la coerenza e l'affidabilità, ma non sono automatici. Un database mal progettato può funzionare male e causare incoerenze. Le transazioni non saranno atomiche se non le rendi tali. Se non usi religiosamente le istruzioni con parametri, ti aprirai agli attacchi SQL injection.


0

Vari giochi memorizzano le cose in diversi modi. Spesso, le società di giochi creano un modo per farlo e la maggior parte dei loro giochi usa lo stesso modo. Naturalmente, diversi studi spesso usano modi diversi. L'SQL è sicuramente usato per i giochi, ad esempio CCP (EVE) ha (o almeno aveva) una rete di server SQL, non sono sicuro di come lo facciano adesso. Altri, usano solo molti file.

Forse iniziare creando un "meccanismo di broker di dati" agnostico, per gestire varie transazioni di dati di gioco? Dal momento che stai solo testando, crea un meccanismo che ti consenta di non doverti preoccupare troppo della memoria, dal punto di vista del gioco stesso. Significato, concentrati su come, dall'applicazione host, gestirai questo.

Personalmente penso che sarebbe un grande vantaggio se si potesse cambiare il negozio reale, senza dover riscrivere il gioco e il broker stesso. Basta passare a un altro modulo con la stessa interfaccia con cui il broker può parlare.

La memorizzazione dei dati in sé non è probabilmente un problema di per sé. La spedizione efficiente dei dati da / verso quel negozio, tra l'host e tutti i clienti, potrebbe essere più complicata. Spedisco l'intero set di dati del giocatore, o se lo scompongo in parti, con quale granularità scelgo di partizionare, ecc. Quale richiede più risorse in quale situazione, ecc.

Un formato in cui spedire i dati potrebbe essere XML. In questo modo puoi essere più facilmente dinamico nel modo in cui puoi farlo a pezzi. Un carattere contro più caratteri o un elemento contro una raccolta di elementi, ecc. È quindi possibile "archiviare" l'XML come XML (in SQL) e / o fare in modo che SQL lo distribuisca in modo più transazionale dall'XML, a come desideri che i dati vengano effettivamente archiviati.

Un altro modo è binario, che è più efficiente in termini di spedizione, ma può comportare maggiori costi in altre situazioni.

Con 1.000 client, è possibile iniziare e archiviare facilmente 10 MB per client e utilizzare solo 10 GB di RAM effettiva + aggiungere un po 'di RAM amministrativa di sistema per la gestione di tali dati, diciamo altri GB o due. È possibile mantenerlo nella RAM sull'host già nella struttura dei dati pronto per l'uso. E carica / salva dinamicamente, a seconda di chi è online, in varie frequenze a seconda dell'attività, ecc.

È anche possibile archiviare le informazioni di ciascun cliente in un file separato e così via.


0

Tieni i giocatori * online * in ram e trasferiscili in un database (SQLite? MySQL?) Quando si disconnettono. se sei preoccupato per lo stallo IO durante il logout, dai a ogni logout il proprio thread, non farlo nel thread principale / di gioco (in realtà tengo un thread player dedicato per ogni giocatore online, ha reso il codice di rete molto più semplice che fare l'approccio asincrono alla rete)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.