Gibt es eine Möglichkeit, eine dynamische Welt wie ein MMORPG horizontal skalierbar zu machen?

11

Stellen Sie sich eine offene Welt mit mehr als 500 Spielern vor, deren Daten sich bis zu 20 Updates / Spieler / Sekunde ändern. Als ich das letzte Mal in einem ähnlichen MMORPG gearbeitet habe, wurde SQL verwendet, so dass die Datenbank nicht ständig abgefragt werden konnte. Stattdessen wurden alle Player aus der Datenbank als C ++ - Objekte in den Speicher geladen und verwendet. Das heißt, es wurde vertikal skaliert. Wäre es möglich, diesen Server stattdessen horizontal skalierbar zu machen? Gibt es eine Datenbank, die diese Anzahl von Updates gleichzeitig unterstützt?

MaiaVictor
quelle
Warum möchten Sie den Player in der Datenbank 20 Mal pro Sekunde aktualisieren?
Balon
@Balon da bin ich verwirrt. Wenn ich es nicht in der Datenbank aktualisiere, sondern nur im Speicher, habe ich unterschiedliche Zustände zwischen verschiedenen Computern. Aber ich denke, DB-Updates haben einen enormen Overhead, sodass es für diese Menge an Updates nicht wirklich funktioniert.
MaiaVictor
2
Wenn Sie wirklich der Meinung sind, dass verschiedene Maschinen (oder sogar Prozesse) 20-Hz-Updates für Hunderte von Objekten benötigen, umgehen Sie die Datenbank vollständig und verwenden Sie ein Messagingsystem direkt. Aber was Sie wirklich, wirklich denken, dass Sie wollen, ist nicht das, was Sie wirklich wollen. Was Sie wollen, ist, einen vernünftigen Überblick darüber zu haben, wer was wissen muss, und dann eine Möglichkeit zu haben, Objekte zwischen den Bereichen sauber zu transportieren. Sie sollten die Frage beantworten, warum Sie 20-Hz-Updates zwischen verschiedenen Computern benötigen, um gute Antworten zu erhalten. Jemand könnte sich eine neue Sichtweise auf das Problem überlegen.
Patrick Hughes
@PatrickHughes Ich weiß nicht, was ich brauche, ich erkläre nur, wie das Spiel funktioniert. Charaktere bewegen sich 2 ~ 3 Kacheln pro Sekunde. Eine Spielerjagd kann von ein paar Monstern umgeben sein, also mindestens 10 Plättchen / Spieler / Sekunde. Dann verfallen Gegenstände auf dem Boden, auf dem Rucksack des Spielers. Es gibt Angriffe in Richtung des Spielers, es gibt Angriffe in Richtung des Monsters. Die Gesundheit nimmt ab, das Mana wird verbraucht, Timer fügen dem Spieler Giftschaden zu. Die Dinge ändern sich also sehr schnell. Dies ist das Spieldesign. Wie könnte ein solches Design vertikal skaliert werden?
MaiaVictor
1
Ich habe das vor einiger Zeit auf HackerNews gesehen: paralleluniverse.co Sie arbeiten an einer Datenbank, die alle räumlichen Segmentierungs- / Verteilungsaufgaben für Sie erledigt. Ich würde vermuten, dass sie unter der Haube all die Dinge tun, die in den Antworten unten aufgeführt sind.
Schlepper

Antworten:

17

Testfall von 500 Spielern, die alle miteinander kommunizieren, das sind 250.000 Informationsströme, die mit 20 Hz herumfliegen. Die interne Bandbreite hierfür würde unter der Annahme von 100 Bytes pro Nachricht etwa 500 MB / s betragen. Klingt ehrgeizig. Besonders zwischen Prozessen.

Wenn Sie Spieler in Gruppen von 100 Personen aufteilen, verringert sich dies auf 20 MB / s und so weiter. Aus diesem Grund haben MMOs Zonen und in diesen Zonen kleine Einflussblasen usw. nach unten, bis die Bandbreite angemessen wird.

Das ursprüngliche Problem kann festgestellt werden, dass wenn Sie 10 Personen haben, die alle Echtzeitinformationen teilen, aber 500 alle teilen möchten , dies ein exponentielles Wachstum der Kommunikationsverbindungen ist und wie wir das umgehen können . Ich befürchte, dass es keine magische Kugel gibt, von der ich jemals gehört habe, die den geometrischen Fortschritt auf magische Weise verschwinden lässt.

Verwenden Sie keine Datenbank für die Kommunikation, dafür ist Messaging gedacht. Verwenden Sie die Datenbank, um Transaktionen zu erzwingen und Informationen zu speichern, die Spieler nicht verlieren sollen. Die meisten MMOs, mit denen ich vertraut bin, aktualisieren die Datenbank nur alle 1-10 Minuten mit dynamischen Player-Informationen oder an praktischen Stellen wie Zonenübergängen oder der Eingabe "sicherer" Zonen im Design.

Möglicherweise müssen Sie den Bedarf des Spiels für jeden Spieler, egal wie weit entfernt, neu gestalten, um Echtzeit-Updates der Rucksackinhalte aller anderen Spieler zu erhalten.

Ändern Sie auch das Aktualisierungsmuster von 20 Hz auf eine Geschwindigkeit, die auf der Entfernung basiert. Jemand, der 1 Meile entfernt ist, muss nicht wissen, dass Sie sich mit genau 230,6 Sekunden um 1 Fuß bewegt haben, und dann mit 231,4 Sekunden um einen weiteren Fuß Sekunden.

Patrick Hughes
quelle
Tolle und informative Antwort, danke. Aber ich könnte hinzufügen, dass sich die Welt zwar sehr schnell verändert, ein Spieler jedoch nur andere Spieler direkt neben sich sehen kann. Ich sehe es nicht als geometrisch an - 500 Spieler senden Informationen an den Server. Der Server sendet regelmäßig Informationen an diese 500 Spieler. Es ist linear, wie ich sehe. Der Hauptpunkt ist jedoch der 4. Absatz: Wenn ich die Datenbank nur zum Speichern verwende, lade ich Daten in den Speicher. Wenn ich Daten in den Speicher eines Computers lade, erstelle ich eine desynchronisierte Version der Welt. Das verstehe ich nicht.
MaiaVictor
Für 1 Client: 1 msg out + 1 msg in = 2. Für 2 Clients: 2 msg out, 2 msg in = 4. Für 3 Clients: 3 msg out, 3 msg in = 9. Und so geht es weiter. Es ist wie folgt: Senden Sie eine Statusnachricht, der Server sendet das Ergebnis an mich und die anderen 2 Clients (1 in, 3 out) und 3 Clients, die dies tun (1 in 9 out). Während es für nur einen der drei Clients linear aussieht, können Sie dies mit allen Clients für den Gesamtdurchsatz des Systems multiplizieren. Bei der Desynchronisierung sind sogar Prozesse auf derselben physischen Box nicht synchron, bis die Statusmeldung erstellt und gesendet wird. Es kommt nur darauf an, wo die Pipe entleert wird, lokaler RAM oder Netz.
Patrick Hughes
5

Verwenden Sie die Filterung des interessierenden Bereichs. Wenn eine Welt in drei Server aufgeteilt ist und sich der Bereich auf Server 1 nicht in der Nähe des Bereichs von Server 3 befindet, gibt es für sie keinen Grund, überhaupt Informationen über Entitäten auszutauschen.

Senden Sie auf einem einzelnen Server nur relevante Informationen an Clients. Befindet sich Spieler A am völlig anderen Ende der Karte als Spieler B, gibt es keinen Grund, Aktualisierungen über B an A zu senden oder umgekehrt.

Wenn Sie mehrere Server in einer kontinuierlichen Welt haben, haben Sie Entitäten in der Nähe eines Randes auf Server 2, die sich in der Nähe von Entitäten auf Server 1 befinden. Sie können Aktualisierungen vom "autorisierenden" Server für eine Entität an den anderen Server senden (falls zutreffend). und leiten Sie alle Nachrichten entsprechend an den autorisierenden Server weiter.

Ja, in diesem Fall ist ein Server für bestimmte Entitäten etwas veraltet. Versuchen Sie nicht, das zu lösen. Komm damit klar. Angenommen, Entitäten sind möglicherweise etwas veraltet. Führen Sie eine Logik aus, die aktuelle Informationen nur auf dem Server benötigt, dem die Entitäten autorisiert gehören. Wenn eine Entität eine andere beeinflusst, senden Sie eine Nachricht und gehen Sie davon aus, dass möglicherweise mehrere Spiellogik-Ticks erforderlich sind, bevor sie verarbeitet und Ihre Ansicht aktualisiert wird.

Dieses Design erleichtert auch das Threading eines einzelnen Servers erheblich. Keine Entität sollte eine andere direkt ändern, nur Nachrichten senden, und die lokalen Proxy-Caches pro Server / pro Thread sollten als etwas veraltet angenommen werden.

Wenn beispielsweise Entität A Entität B angreift, überprüfen Sie nicht die Lebensdauer von B und senden Sie dann eine Todesnachricht, wenn sie 0 erreicht. Senden Sie einfach eine "beschädigte" Nachricht, lassen Sie den autorisierenden Server für B damit umgehen und behandeln Sie dann eine beliebige Nachricht Nachricht "Entität gestorben", die später von Server B gesendet wird, wenn Entität A sich darum kümmert.

Gleiches gilt für alle großen, skalierbaren Nicht-Spiele-Anwendungen. Eine zentrale Datenbank ist keine magische Instant-Sharing-Technologie. Zwei Server müssen asynchron stapelweise mit Nachrichten kommunizieren, um einen hohen Durchsatz aufrechtzuerhalten. Daher die Popularität von Technologien wie AMPQ und dergleichen. Datenbanken dienen der Speicherung und unterstützen die Synchronisierung, da sie für die Kommunikation verwendet werden können, nicht weil sie selbst für die Synchronisierung oder Kommunikation gedacht sind.

Sean Middleditch
quelle
Danke, das hat die meisten meiner verbleibenden Zweifel beendet. Sie haben mir auch die Idee gegeben, die Server nach Spielern und nicht nach Bereichen zu trennen - dies würde reibungsloser aussehen. Jeder Server kümmert sich um x Spieler. Das gefällt mir wirklich gut! Wird das benutzt? Und es gibt nur noch eine Sache. Wie ich oben gefragt habe, habe ich gerade etwas über eine neue NoSQL-Datenbank erfahren, Couchbase. Es soll genau wie CouchDB sein, nur mit sehr schnellen Schreib- / Lesegeschwindigkeiten: bis zu 200.000 Updates pro Sekunde! Vielleicht könnte dies tatsächlich als solches "Echtzeit-Modell der gemeinsamen Welt" funktionieren, oder noch nicht?
MaiaVictor
Ich habe keine Ahnung, ob diese Technik in freier Wildbahn neben dem üblichen groben "Sharding" von Servern angewendet wird. Wenn Sie dies nur nach Spielern und geografischem Gebiet tun, muss jeder Server möglicherweise eine sehr große Anzahl von Entitäten in verschiedenen Bereichen kennen, was die Serverlast und die Kommunikation zwischen Servern erheblich erhöht. Wenn Sie dies nach Bereich tun, wird Ihr Server möglicherweise in überfüllten Bereichen überlastet (obwohl Sie in diesem Fall Bereiche dynamisch teilen und verbinden können), aber jeder Server verfügt über einen kleineren Satz relevanter Nicht-Spieler-Entitäten und -Geometrien, die Sie verfolgen können .
Sean Middleditch
@Dokkat: Es kann möglich sein, dass es eine Art "weicher Bereich" gibt, in dem jeder Server hauptsächlich Spieler in einem bestimmten Teil der Spielwelt behandelt, den Spieler jedoch transparent an einen anderen Server übergibt, wenn er zu weit davon entfernt ist die Region ihres ursprünglichen Servers. Sie müssen nur sicherstellen, dass die Übergabe reibungslos genug ist, damit die Spieler es nicht wirklich bemerken. Sie könnten sogar versuchen, einige ausgefallene adaptive Techniken zu verwenden, um Cluster interagierender Spieler auf demselben Server zu halten, selbst wenn sie sich zufällig nur an einer Regionsgrenze befinden.
Ilmari Karonen
3

Sie werden wahrscheinlich in interessieren diesen Artikel auf Gamasutra , wo Eve Online - Entwickler diskutieren , wie es möglich ist , erfolgreich ein Spiel mit 400 000 aktiven Spielern ... in einer SQL - Datenbank auszuführen.

Liosan
quelle
2

Stellen Sie sich die Datenbank nicht als ein gemeinsames Echtzeit-Weltmodell vor, in dem jederzeit alles gespeichert ist - wie Sie bemerkt haben, kann dies unmöglich funktionieren.

Behandeln Sie die Datenbank stattdessen eher wie eine automatisch aktualisierte Sicherungsdatei: Sie aktualisieren die Datenbank nur gelegentlich, z. B. wenn sich Spieler anmelden oder abmelden oder von einer Zone in eine andere wechseln oder wenn etwas Wichtiges passiert, das Sie nicht möchten verloren im Falle eines Serverabsturzes.

Der tatsächliche Echtzeit-Weltstatus sollte von den Spielservern wie in Ihrem ursprünglichen Beispiel im Speicher gehalten werden. Der Trick für die horizontale Skalierung besteht nun darin, dass nicht jeder Server zu jedem Zeitpunkt alles wissen muss . Wenn beispielsweise Spieler A in Zone A auf Server A spielt, muss Server B, auf dem Zone B ausgeführt wird, normalerweise nicht wissen, was Spieler A in seinem Rucksack hat - und wenn er dies aus irgendeinem Grund wissen muss (z. Da Spieler B in Zone B eine Art Fernspionagezauber auf A) ausübt, kann er einfach den anderen Server nach diesen Informationen fragen .

Dies erfordert, dass Sie den Servern klare Verantwortlichkeiten zuweisen, damit Server B, wenn er etwas über den Rucksack von Spieler A wissen möchte, weiß, welcher Server die maßgeblichen Informationen dazu hat. Sie werden wahrscheinlich auch eine Art Update-Abonnement-Mechanismus einbinden wollen, so dass z. B. Server B Server A einfach mitteilen kann: " Ich habe jemanden, der Spieler A ausspioniert. Halten Sie mich über alles auf dem Laufenden, was er tut, bis ich Ihnen etwas anderes sage. " Sie möchten auch eine Art globales Rundfunksystem für wichtige globale Ereignisse einbinden, über die die Spieler möglicherweise Bescheid wissen müssen, unabhängig davon, wo sie sich befinden. Natürlich sollten solche Ereignisse auch in der Datenbank aufgezeichnet werden. Wenn sie jedoch aktiv an alle Server gesendet werden, müssen die Server die Datenbank nicht ständig nach Updates abfragen.

Ilmari Karonen
quelle
Super Antwort! Genau das habe ich gefragt, danke. Vielleicht besteht der Schlüssel darin, den Server in Bereiche zu unterteilen und die Logik im On-Speicher zu belassen. Könnte ich aber hinzufügen: Ich habe gerade etwas über eine neue NoSQL-Datenbank gelernt, Couchbase. Es soll genau wie CouchDB sein, nur mit sehr schnellen Schreib- / Lesegeschwindigkeiten: bis zu 200.000 Updates pro Sekunde! Vielleicht könnte dies tatsächlich als solches "Echtzeit-Modell der gemeinsamen Welt" funktionieren oder noch nicht?
MaiaVictor
@Dokkat nein, wird es nicht. Couchbase ist keine Magie.
Philipp
2

Andere Antworten haben gute Arbeit geleistet, um darauf hinzuweisen, wie eine Datenbank verwendet wird und keine Datenbank für die Kommunikation. Ein weiterer Aspekt, den Sie möglicherweise untersuchen, besteht darin, Ihre Aktualisierungen danach zu kategorisieren, wie die Informationen an andere Entitäten übermittelt werden müssen. Anstatt die Kommunikation mit Servern zu erweitern, können Sie Ihre Nachrichten verteilen und Pubsub-Mechanismen für die Kommunikation von Updates zwischen Entitäten verwenden. Beispielsweise können Sie den Standort unterschiedlich behandeln, je nachdem, wer Ihnen nahe steht:

  • Innerhalb des Radius R kann eine genaue Echtzeitposition nützlich sein
  • Innerhalb von Radius 2 * R können weniger genaue und weniger häufige Standortaktualisierungen hilfreich sein
  • Über den Radius 2 * R hinaus sind möglicherweise keine Standortinformationen erforderlich

Sie können Standortinformationen für eine Entität übermitteln, indem Sie regelmäßig nach Entitäten innerhalb des Radius 2 * R (oder einem Vielfachen davon basierend auf der Aktualisierungsrate und der maximalen Geschwindigkeit einer Entität) suchen und die Entität für den genauen oder ungenauen Standortfeed der anderen Entität abonnieren.

Sie können unterschiedliche Strategien für unterschiedliche Arten von Informationen verwenden, gemeinsame Dinge in denselben Nachrichtenwarteschlangen gruppieren oder unterschiedliche Warteschlangen für Nachrichten haben, die an verschiedene Entitäten gesendet werden müssen (oder sie einfach an die breiteste Gruppe von Entitäten senden und Nachrichten verwerfen lassen, wenn sie verworfen werden sind nicht nützlich).

David N.
quelle