Wie speichert mmorpg Daten?

22

Ich möchte die SQL-Datenbank in meiner server.exe verwenden.

Sagen wir 1000 Benutzer online. Und die Spieler ändern ihre Daten, wenn sie spielen. Und Server müssen diese Updates speichern.

Aber wie ?

Ich denke da in zwei Richtungen:

1) Der Server speichert zur Laufzeit im RAM und der Server schreibt irgendwann oder stündlich Daten (Aktualisierung) von RAM in die SQL-Datenbank. Wenn der Strom ausfällt oder der Server ausfällt, werden keine Updates gespeichert. Natürlich möchte ich keine Updates verlieren.

2) Der Server speichert die Aktualisierungen zur Laufzeit in der Datenbank. aber was passiert mit der Geschwindigkeit? Ich dachte an eine Methode. Ich werde Sie unten mit Bild zeigen. Kann ich mit dieser Methode genug Geschwindigkeit für 1000 Online-Spieler erreichen? Bildbeschreibung hier eingeben

Emre Kaya
quelle
11
Haben Sie Benchmarks durchgeführt? Was lässt Sie denken, dass Datenbankoperationen ein Problem für Ihr Spiel darstellen würden?
Congusbongus
3
Ist Ihr Spiel tatsächlich relational? Möchten Sie wirklich eine SQL-Datenbank?
Hör auf, Monica
6
Lesen Sie auch, wie Sie mit Passwörtern umgehen, die Hashes verwenden. Oder informieren Sie den Benutzer zumindest darüber, dass sein Kennwort als einfacher Text gespeichert wird, damit er kein anderes sicheres Kennwort verwenden darf.
TomTsagk
24
Nebenbei bemerkt, wenn Sie ein kommerzielles MMO erstellen möchten und Fragen wie diese stellen, sollten Sie wahrscheinlich mit etwas Kleinerem beginnen. MMOs sind unglaublich schwer zu machen, geschweige denn richtig zu machen, und sie sind aus geschäftlicher Sicht nicht so großartig. Wenn dies nur eine persönliche Sache ist und Sie eine hohe Anzahl von Spielern anstreben, beginnen Sie mit 64 Spielern und arbeiten Sie sich dann nach oben. Es wird viel einfacher sein, als zu versuchen, die "perfekte" Architektur ohne Erfahrung von Grund auf neu zu entwerfen. Sieh das .
Fund Monica Klage
1
Sie können eine allgemeine API schreiben, die speicherunabhängig ist. Schreiben Sie dann einen Adapter, der Daten im RAM für eine verzögerte Speicherung zwischenspeichert. Oder Sie können einen Adapter schreiben, der Daten in einer temporären Datei zwischenspeichert, bevor sie in die SQL-Datenbank geschrieben werden. Auf diese Weise können Sie die Zwischenspeicherung ein- und ausschalten, um herauszufinden, welche am besten ist. Sie müssen nicht zu viel zusätzlichen Code schreiben, wenn Sie Ihre Architektur richtig gebaut haben.
0xC0DEGURU

Antworten:

37

Die meisten MMOs (oder Projekte mit ähnlicher Architektur), an denen ich gearbeitet habe oder die ich kenne, verwenden die erste Methode: Die Spielserver arbeiten hauptsächlich mit dem RAM auf den Computern, auf denen die Serverprozesse ausgeführt werden, und serialisieren die relevanten Spieldaten nur regelmäßig in eine SQL-Datenbank zur Archivierung (falls überhaupt eine verwendet wird).

Die Probleme, die Sie aufgrund eines Stromausfalls feststellen, sind gültig, aber weniger wahrscheinlich als Probleme wie Abstürze im Prozess (Zuverlässigkeit der Betriebszeit ist im Allgemeinen eines der Dinge, für die Sie das Rechenzentrum bezahlen würden). Aber dennoch. Sie verringern diese Probleme, indem Sie beispielsweise das Sicherungsintervall optimieren (ein Fehler kostet höchstens ein paar Minuten Fortschritt), die Sicherungswarteschlangen auf mehrere Computer verteilen, die zu sichernde Datenmenge aggressiv einschränken und eine neu startbare Sicherung implementieren Warteschlangen.

Im Allgemeinen ist die Verwendung des SQL-Servers als Hauptspeicher unangenehm langsam (und umständlich). Ich sehe dort nicht genug Details in Ihrem Vorschlag, um sicher sagen zu können, ob es nur für ungefähr 1000 Spieler funktionieren würde - es wäre wahrscheinlich in Ordnung. Aber ich glaube nicht, dass Sie es aggressiv skalierbar machen können.

Außerdem löst es das Problem nicht. Ein Stromausfall während des Speichervorgangs wird weiterhin Daten verlieren oder beschädigen, es sei denn, Sie implementieren die gleiche Art von neu startbarer Speicherwarteschlange (was selbst dann die Wahrscheinlichkeit eines katastrophalen Datenverlusts nur erheblich verringert, aber nicht verhindert). .

Ich würde empfehlen, dass Sie mit dem ersten Ansatz gehen.

Josh
quelle
10
In Bezug auf "Einstellen des Speicherintervalls" hatte das letzte MMO, an dem ich gearbeitet habe, ein Speicherintervall, das auf der Anzahl der aktiven Spieler basierte. Wir wussten, dass es möglich ist, die Daten von X Spielern pro Sekunde zu speichern, ohne dass es zu einem spürbaren Engpass kommt. Daher haben wir nur ein bisschen weniger als X Spieler pro Sekunde auf einer rotierenden Basis gespeichert. In der Regel war es an arbeitsreichen Tagen alle zwei Minuten eine Ersparnis für jeden Spieler, in den langsamen Zeiten sogar zweimal pro Minute.
Meanbits
4
"Restartable Save Queue" klingt wie ein Journal, wie es von vielen Dateisystemen und Datenbank-Engines implementiert wird?
Grawity
6
Diese Probleme sind nicht einzigartig für MMOs oder sogar Videospiele, überhaupt . Nahezu jeder existierende ORM bietet eine Art Caching / Batching-Mechanismus. Sie müssen keine eigene Lösung entwickeln.
BlueRaja - Danny Pflughoeft
3
Wenn Sie dennoch in einem bestimmten Intervall auf eine Festplatte speichern möchten, empfehlen wir Ihnen, ein System zu entwickeln, in dem die Daten sofort gespeichert werden können, wenn die Leute einen seltenen Sturz / Würfel / usw. erhalten. Auf diese Weise sind Menschen, die etwas Großes erreicht haben, bei einem Server-Absturz oder Ähnlichem nicht zu verärgert.
Jon
5
@Jon, und dann stoßen Sie auf das Problem, dass Benutzer Objekte duplizieren können. Im Idealfall speichern Sie den gesamten Spielstatus regelmäßig als einzelne Transaktion. Sobald Sie stückweise mit dem Speichern beginnen, werden Sie mit Situationen konfrontiert, in denen ein Absturz inkonsistente Daten verursachen kann. Spieler, die bei Bedarf einen Absturz auslösen oder sogar vorhersagen können, wann ein Absturz wahrscheinlich ist, können dies zu ihrem Vorteil nutzen.
Mark
15

1000 Spieler können ein Problem sein oder auch nicht. Dies hängt davon ab, wie oft Sie die Datenbank aktualisieren müssen. Es gibt jedoch eine einfache Lösung: Platzieren Sie die Datenbank auf einem eigenen Server.


Ich habe einen Blick darauf geworfen, wie das Datenbanksystem in einem Spiel funktioniert, das die Leute als MMO-Lite bezeichnen würden - was ich nicht preisgeben werde -, aber ich kann sagen, dass es durchweg mehr als 1000 Spieler hat. Dies ist die Zusammenfassung:

  • Sie verwenden eine dokumentbasierte "No-SQL" -Datenbank für private Charakterinformationen (Inventar, Ausrüstung, Ähnliches).
  • Sie verwenden eine traditionellere relationale Datenbank für Informationen zu öffentlichen Charakteren, die selten aktualisiert werden (Name, Erfolge usw.) und Statistiken.

In diesem Fall ist die Verwendung einer dokumentbasierten Datenbank eine gute Idee für die Leistung. Es ist gut, auf die Daten zuzugreifen, auch wenn es schlecht ist, um Verknüpfungen und Aggregationen durchzuführen ... aber sie werden das nicht mit den Daten tun, die sich dort befinden.

Auf der anderen Seite, wenn sie so etwas wie das Ändern eines Objekts mit einem anderen Objekt für alle tun müssen, und wenn ein Hintergrundskript ausgeführt werden muss, das zeichenweise abläuft und einzeln aktualisiert wird, dauert es merklich lange.


Die Daten des Charakters sind sowohl auf dem Client als auch auf dem Server vorhanden, und das System ist so ausgelegt, dass sie synchron bleiben und auf beiden Seiten dieselben Vorgänge ausführen.

Wenn nun ein Spieler eine Transaktion mit dem System durchführt - zum Beispiel einen Gegenstand über einen NPC oder Ähnliches gegen einen anderen austauschen - hat dies folgende Stufen:

  • Der Client prüft, ob die Operation gültig ist
  • Der Client sendet die Operation an den Server (asynchrone Operation)
  • Der Client aktualisiert sein Modell im RAM
  • Der Server prüft, ob der Vorgang gültig ist
  • Der Server aktualisiert sein Modell im RAM
  • Der Server aktualisiert die Datenbank (asynchrone Operation)
  • Der Server teilt dem Client mit, dass die Änderung stattgefunden hat

Anmerkungen :

  • Obwohl die Datenbankaktualisierungen asynchron sind, werden sie sofort durchgeführt. Wenn der Spieleserver aus irgendeinem Grund ausfällt, geht nicht viel verloren.
  • Leistungseinbußen sind keine große Sache, da die Datenbanken auf eigenen Servern gespeichert werden.

Trades zwischen Spielern werden ähnlich gehandhabt, mit zusätzlichen Regeln, um zu verhindern, dass Spieler andere Spieler betrügen, und zusätzlicher Rückverfolgbarkeit, falls eine Transaktion rückgängig gemacht werden muss. Ich habe gehört, dass es spezielle Protokolle aller Transaktionen gibt, die für einige Zeit aufbewahrt werden (um Probleme zu lösen, wenn sich jemand beschwert). Ich weiß nicht mehr, wie dieser Teil funktioniert.


Manchmal geht etwas schief, dies hat zwei mögliche Folgen:

  • Wenn der Fehler sofort auftritt, teilt der Server dem Client mit, dass der Vorgang rückgängig gemacht werden soll (der Player sieht, dass der Vorgang rückgängig gemacht wird).
  • Die Benutzeroberfläche sagt, der Spieler hat einen Gegenstand, aber der Server stimmt nicht zu. Wenn der Benutzer versucht, es zu verwenden, fragt es den Server und schlägt fehl, wodurch das gefälschte Objekt unbrauchbar wird. Das falsche Objekt verschwindet, wenn das Inventar neu geladen wird, was als Gelegenheit zur Synchronisierung des Modells genutzt wird.

In beiden Fällen ist der Client über den Fehler informiert und protokolliert ihn zusammen mit allem, was der Spieler getan hat. Die Client-Seite wird ständig protokolliert. Wenn beim Abmelden ein Fehler aufgetreten ist, sendet der Client die Protokolle an den Server.


Dieses Spiel verwendet nicht die üblichen täglichen oder wöchentlichen Wartungsunterbrechungen, die die meisten MMORPGs haben. Diese geplante Wartung wird häufig zum Zurücksetzen von Zählern, Zeitgebern und Ausführen von Datenbankprozeduren verwendet. Sie bieten auch die Möglichkeit, Serverversionen gegen ein Update auszutauschen.

Theraot
quelle
Danke, aber was ist zum Beispiel mit den Bewegungen der Spieler, wenn sich ein Spieler von seiner aktuellen Position bewegt: x:10,y:10,z:10An x:11,y:11,z:11, sollte dies sofort in der Datenbank gespeichert werden? Wenn der Spieler weiterläuft, bedeutet dies, dass wir seine aktuelle Position alle 1 Sek. oder weniger speichern. Wenn es Tausende von Spielern gibt, sind das Millionen von Abfragen an die Datenbank pro Sekunde. Funktioniert das so?
Dwix
2
Die Position des Spielers sollte sehr selten in der Datenbank gespeichert werden. Das möchte man nur zu besonderen Anlässen wie dem Öffnen des Menüs, dem Starten eines Lagerfeuers, dem Ausruhen usw. Je nach Spiel wird es nicht einmal so detailliert gespeichert. Bei manchen Spielen laicht man immer in der nächstgelegenen Stadt usw., so dass das Speichern der Position ebenfalls mühsam ist. Aber das driftet in meinungsbasierte.
Nico
1
@dwix Bei dem Spiel, über das ich spreche, wird die Position des Spielers nicht einmal gespeichert. Wenn Sie sich abmelden und anmelden oder wenn der Server ausfällt, wird der Player wieder an eine sichere bekannte Position gebracht (Bearbeiten: Es ist eine private Instanz, wenn Sie so wollen "Haus", aber es ist für alle gleich). Einige Spiele behalten jedoch die exakte Position des Spielers bei, auch bei versehentlichem Trennen. Zu diesem Zweck werden diese Informationen normalerweise weniger häufig gespeichert. Unabhängig davon macht man nicht was der Server auf der Datenbank wartet.
Theraot
1
@dwix Wenn Sie über die Position des Avatars sprechen, interessieren Sie sich nicht wirklich für historische Werte, oder? Nun, wenn die Datenbank ein Flaschenhals ist, dann drosseln Sie die Daten. Speichern Sie nicht jeden Server-Tick, sondern weniger häufig. Dies bedeutet, dass die Datenbank nicht den aktuellsten Wert hat, die Leistung jedoch nicht so stark beeinträchtigt wird. In der Zwischenzeit behält der Server den Aktualisierungswert im RAM bei, und damit funktioniert es. Nachtrag: Ehrlich gesagt würde ich davon abraten, die Positionen zu speichern, aber einige Spiele tun das.
Theraot
1
@ Dwix siehe Meanbits Kommentar
Theraot
7

Beide Ansätze werden mit MMORPGs verwendet. Es scheint die beliebteste Option zu sein, alles im Speicher zu belassen und regelmäßig zu überprüfen, ob es auf die Festplatte verweist, zumindest für ältere Spiele. Es hat den Vorteil, dass es relativ einfach zu implementieren und relativ gut zu skalieren ist. Die Zuverlässigkeit liegt jedoch ganz bei den Entwicklern. SQL-Datenbanken bieten ACID-Eigenschaften , die die Zuverlässigkeit vereinfachen, insgesamt aber schwieriger zu implementieren sind und Probleme bei der Skalierung verursachen können.

EVE Online ist ein Beispiel für ein MMO, in dem alles in einer SQL-Datenbank gespeichert ist. Meiner Meinung nach lag der Höchststand bei etwa 60.000 gleichzeitigen Benutzern, und im Laufe der Jahre musste teure Hardware für die Datenbankserver bereitgestellt werden, um mit der Last Schritt zu halten. EVE speichert jedoch viel mehr Daten pro Benutzer als die meisten MMORPGs und hat viel häufigere und vielfältigere Transaktionen. Die ACID-Eigenschaften der Datenbank ermöglichen es, die gesamte massive und komplizierte Datenbank immer in einem konsistenten Zustand zu halten.

Betrachten Sie zum Beispiel den Fall, dass jemand einem anderen Spieler einen Gegenstand gibt. Die Datenbank von EVE garantiert, dass der Gegenstand auch bei einem Absturz oder Stromausfall nur im Inventar eines Spielers landet. Das heißt, die Datenbanktransaktion, die den Gegenstand aus dem Inventar eines Spielers entfernt und zum Inventar des anderen Spielers hinzufügt, ist atomar. Die Transaktion wird entweder vollständig abgeschlossen oder überhaupt nicht ausgeführt. Sie können nicht in einem Zustand enden, in dem der Gegenstand weder im Inventar der Spieler noch in beiden vorhanden ist.

Ein MMORPG, das Spielerdaten im Speicher hält und diese regelmäßig überprüft, muss diese Atomizität selbst implementieren. Eine Möglichkeit, dies zu tun, besteht darin, die Daten aller Spieler gleichzeitig zu überprüfen und sicherzustellen, dass der neue Prüfpunkt vollständig auf die Festplatte übertragen wird, bevor er als der letzte Prüfpunkt betrachtet wird. Das Spiel müsste auch sicherstellen, dass sich die Spielerdaten nicht ändern können, während sie überprüft werden. Bei einer großen Anzahl aktiver Spieler wird die Herausforderung all dies tun, ohne eine Verzögerung zu verursachen, die die Spieler bemerken würden.

Unterschätzen Sie nicht, wie wichtig Konsistenz ist. Wenn du dein Spiel entwickelst, wird es sehr abstürzen. Sie möchten nicht herausfinden müssen, warum Elemente verschwinden und / oder dupliziert werden, und nicht, wenn das Problem darin besteht, dass ein nicht verwandter Fehler das Spiel zu einem schlechten Zeitpunkt zum Absturz bringt. Wenn Ihr Spiel live geht, stürzt es außerdem weitaus mehr ab, als Sie erwarten. Ihr Server, der unter Testbedingungen einwandfrei funktionierte, wird plötzlich zahlreiche Fehler unter Volllast aufdecken und Spieler tun, was Sie nicht erwartet haben.

Beachten Sie, dass die meisten MMORPGs SQL-Datenbanken für kontobezogene Informationen verwenden, auch wenn sie keine tatsächlichen Spieldaten enthalten. Noch wichtiger als das Beibehalten des Spielstatus ist das Beibehalten des Abrechnungsstatus. Das Schlimmste daran, dass die Spieldatenbank beschädigt wird, ist, dass Sie die Datenbank aus einer täglichen Sicherung wiederherstellen müssen. Das Schlimmste daran, dass die Kontodatenbank beschädigt wird, ist, dass Sie wegen aller Rückbuchungen bankrott gehen.

Für Ihr Projekt können Sie wahrscheinlich beide Wege gehen. Mit 1000 gleichzeitigen Benutzern werden die Grenzen dessen, was ein SQL-Server heutzutage auf einem Standard-PC kann, wahrscheinlich nicht überschritten, aber vieles wird von der Art der Transaktionen abhängen. Wenn Sie mit SQL und dem Entwurf relationaler Datenbanken vertraut sind, kann dies für Sie hilfreich sein. Sie möchten die Transaktionen so weit wie möglich minimieren. Bei aktuellen Hitpoints des Spielers möchten Sie diese möglicherweise nur regelmäßig in der Datenbank speichern, da Statistiken wie diese nicht unbedingt konsistent sein müssen. (Im PvP-Spiel könnten sie jedoch ...) Speichern Sie keine Objekte wie Monster-HP in der Datenbank, da in den meisten Spielen nur spielerbezogene Daten persistent sind.

Wenn Sie jedoch kein SQL-Assistent sind, ist es möglicherweise einfacher, alle Daten im Arbeitsspeicher zu behalten, damit Sie zuverlässig arbeiten können. SQL-Datenbanken vereinfachen die Konsistenz und Zuverlässigkeit, sind jedoch nicht automatisch. Eine schlecht gestaltete Datenbank kann schlecht funktionieren und zu Inkonsistenzen führen. Transaktionen werden nicht atomar sein, es sei denn, Sie machen sie so. Wenn Sie parametrisierte Anweisungen nicht religiös verwenden, sind Sie SQL-Injection-Angriffen ausgesetzt.

Ross Ridge
quelle
0

Verschiedene Spiele speichern Dinge auf unterschiedliche Weise. Oft schaffen Spielefirmen einen Weg, dies zu tun, und die meisten ihrer Spiele verwenden den gleichen Weg. Natürlich verwenden verschiedene Studios oft unterschiedliche Methoden. SQL wird sicherlich für Spiele verwendet, zB CCP (EVE) hat (oder hatte zumindest) ein Netzwerk von SQL-Servern, ich bin nicht sicher, wie sie es jetzt tun. Andere verwenden einfach viele Dateien.

Beginnen Sie vielleicht damit, einen agnostischen "Datenvermittlungsmechanismus" zu erstellen, um verschiedene Spieldaten-Transaktionen abzuwickeln? Da Sie sowieso nur testen, sollten Sie einen Mechanismus erstellen, mit dem Sie sich vom Standpunkt des Spiels aus nicht allzu sehr um den Speicher kümmern müssen. Konzentrieren Sie sich also darauf, wie Sie in der Host-Anwendung damit umgehen.

Persönlich denke ich, dass es ein großer Vorteil wäre, wenn Sie den eigentlichen Shop wechseln könnten, ohne das Spiel und den Broker selbst neu schreiben zu müssen. Wechseln Sie einfach zu einem anderen Modul mit derselben Schnittstelle, mit dem der Broker kommunizieren kann.

Das Speichern von Daten an sich ist an sich wahrscheinlich kein Problem. Ein effizienter Versand von Daten zwischen dem Host und allen Kunden zu / von diesem Geschäft könnte schwieriger sein. Versende ich den gesamten Player-Datensatz oder teile ich ihn in Teile auf, nach welcher Granularität ich partitioniere usw. Welcher ist in welcher Situation ressourcenintensiver usw.

Ein Format zum Versenden der Daten könnte XML sein. Auf diese Weise können Sie dynamischer sein, wie Sie es aufteilen können. Ein Zeichen gegen mehrere Zeichen oder ein Element gegen eine Sammlung von Elementen usw. Sie können dann entweder das XML als XML (in SQL) "speichern" und / oder SQL veranlassen, es in einer transaktionaleren Art und Weise von XML zu verteilen Wie sollen die Daten tatsächlich gespeichert werden?

Ein anderer Weg ist der binäre Weg, der in Bezug auf den Versand effizienter ist, in anderen Situationen jedoch höhere Kosten verursachen kann.

Bei 1.000 Clients können Sie zunächst 10 MB pro Client speichern und nur 10 GB effektiven Arbeitsspeicher verwenden. Fügen Sie ein paar Systemverwaltungs-Arbeitsspeicher hinzu, um diese Daten zu verwalten, beispielsweise ein oder zwei weitere GB. Sie könnten das im RAM auf dem Host bereits in Datenstruktur einsatzbereit halten. Und laden / speichern Sie dynamisch, abhängig davon, wer online ist, in verschiedenen Frequenzen, abhängig von der Aktivität usw.

Sie können die Informationen jedes Kunden sogar in einer separaten Datei speichern und so weiter.

rauben
quelle
0

Lasse * Online * -Spieler im RAM und schiebe sie auf eine Datenbank (SQLite? MySQL?), Wenn sie sich abmelden. Wenn du dir Sorgen machst, dass die E / A während des Abmeldevorgangs blockiert, gib jedem Abmeldevorgang einen eigenen Thread, mache das nicht im Haupt- / Spiel-Thread (eigentlich habe ich für jeden Online-Spieler einen eigenen Player-Thread, das hat den Netzwerkcode so viel einfacher gemacht) als die asynchrone Netzwerk io Ansatz zu tun)

Hanshenrik
quelle