Format de journal de jeu pour les serveurs MMO


12

Un journal des événements de jeu (par opposition aux journaux d'erreurs / de débogage) pour un cluster / fragment entier est très utile pour un MMO commercial qui se trouve dans un environnement de production en direct, fournissant un support vital pour le service client et les moyens d'analyse historique.

Le projet sur lequel je travaille actuellement utilise une base de données relationnelle pour stocker tous les journaux d'événements de jeu, et bien que cette méthode fonctionne bien, il me semble que la nature chronologique en lecture seule des journaux permettrait un format de stockage plus efficace. .

Cependant, je ne sais pas par où commencer pour apprendre à créer des formats de journaux binaires personnalisés. Quelles sont vos expériences avec la création de formats de journaux personnalisés ou de tout article / article recommandé sur le sujet?

Réponses:


7

Dans Stendhal, nous avons résolu le problème de performances en ajoutant des événements de jeu à une file d'attente, puis en les traitant de manière asynchrone en arrière-plan .

Dans notre cas, les événements ne sont pas seulement des enregistrements mais des objets qui ont un peu de logique car dans certains cas, nous devons faire deux insertions avec un lien entre eux. Par exemple, la première fois qu'un élément est traité dans le jeu, il doit d'abord être inséré dans la table des éléments avant qu'un événement d'élément puisse être enregistré.

Mais l'écriture du journal n'est qu'un aspect du problème:

À quelles questions voulez-vous répondre avec les journaux?

Il est facile de simplement lire le journal complet par ordre chronologique; ou pour le filtrer pour un joueur.

Mais il pourrait y avoir des questions comme:

  • Quels objets Anton a mis au sol qui ont été ramassés par Beth hier? Quel joueur les possède maintenant? (Anton s'est plaint du vol de son objet)
  • De combien de temps un joueur moyen a-t-il besoin pour atteindre le niveau 100? Quels joueurs ont été beaucoup plus rapides? uniquement pour les premiers personnages?
  • Y a-t-il des joueurs qui gèrent d'énormes sommes d'argent? À quels joueurs est-il transmis? Sans rien de précieux en retour?
  • Les joueurs faibles sont-ils capables de tuer des créatures fortes qu'ils ne devraient pas pouvoir tuer légalement?
  • ...

Dans Stendhal, nous utilisons une base de données relationnelle pour les journaux de jeu car c'est le moyen le plus simple d'autoriser des requêtes ad-hoc performantes. Si vous utilisez un format de journal personnalisé, vous devez essentiellement coder toutes ces requêtes en cas de besoin. Et cela avec des performances suffisantes devient plutôt difficile.

Notre table gameEvents a 51 429 139 lignes (l'année dernière) et nous avons une table dédiée au journal des objets qui a 60 360 657 lignes (en tout temps) pour 15 893 831 articles.


Quelle est la vitesse de recherche dans votre base de données? J'ai une base de données similaire avec des journaux et nous avons environ 100 000 000 de lignes après trois mois. Nous utilisons MySQL comme stockage et ses performances sont mauvaises. Une requête simple qui répertorie toutes les actions d'un joueur (seulement 20 000) lignes prend souvent plus de 60 secondes.
Balon

1
Les requêtes simples sur les colonnes d'index sont instantanées. Les requêtes complexes peuvent prendre un peu de temps, des requêtes de 60 secondes se produisent, mais elles sont très rares. Nous avons indexé la table très fortement et compensé la pénalité à l'insertion en les faisant de manière asynchrone.
Hendrik Brummermann

Hmmm je pense que mon problème est que le jeu de résultats est assez grand, souvent entre 3000 et 150000 enregistrements pour un joueur. Cela peut donc être la raison pour laquelle cela prend si longtemps, car cela fonctionne très rapidement pour les petits ensembles de résultats.
Balon

4

Qu'entendez-vous par efficacité? Qu'il s'agisse de la taille du disque ou de la vitesse des requêtes, une base de données relationnelle va presque certainement battre ou égaler votre format binaire propriétaire, et être beaucoup plus facile et plus flexible à utiliser.

Chaque table que vous utilisez dans une base de données relationnelle vous permet à peu près de spécifier à l'octet exact combien d'espace par ligne vous allez autoriser. Si vous ne consignez pas du texte brut - et "le journal des événements de jeu (par opposition aux journaux d'erreurs / de débogage)" implique que vous ne l'êtes pas, ou du moins n'en avez pas besoin - alors l'approche de champ à largeur fixe d'un La base de données relationnelle est plutôt proche de l'optimalité en termes d'espace, ce qui les rend assez rapides en premier lieu. En plus de cela, les bases de données relationnelles sont assez pratiques pour créer des index pour un accès très rapide et optimiser les requêtes pour en tirer le meilleur parti.

Je recommanderais donc de rester avec ce que vous avez.


Merci pour la réponse (et merci aux autres qui ont soumis des réponses ci-dessous)! Plus j'y pense, plus il semble qu'un SGBDR soit la bonne solution pour ce type particulier de journalisation. Il ne serait pas trop difficile de concevoir un format de journal personnalisé bien indexé pour les types de recherche de base, mais avec le type de requêtes compliquées qui sont souvent utilisées par les CSR et l'analyse de jeu, une approche plus générale est nécessaire - à quel point un produit établi va surperformer dans la plupart des cas.
Charles Ellis

La configuration personnalisée du journal des événements serait pratique pour la lecture strictement chronologique, comme les enregistrements de démonstration FPS, mais c'est un problème très différent à résoudre. Quelqu'un a-t-il de l'expérience dans le développement de quelque chose de similaire aux enregistrements de démonstration pour les jeux client-serveur massivement multijoueurs?
Charles Ellis

Selon votre modèle de traitement logique côté serveur, il peut être possible de simplement stocker chaque entrée, horodatée avec l'heure d'arrivée sur le serveur, qui peut être rejouée. Le problème a tendance à venir lors de la lecture, car vous devez rejouer chaque entrée ainsi que modéliser tout autre facteur (par exemple, les graines aléatoires, les entrées implicites telles que les choses qui changent en fonction de la latence, etc.). Mais il n'y a pas ici de système universel - cela dépend du fonctionnement de votre serveur.
Kylotan

3

Il est vrai que vous pourriez probablement enregistrer quelques octets avec un format personnalisé, ou même simplement du texte compressé, le stockage est bon marché, donc cela ne vaut vraiment plus la peine d'être optimisé. Ce qui est plus important, c'est de gérer des choses comme la mise en mémoire tampon et l'interrogation des E / S, ce que fait probablement un serveur SQL standard. Si cela fonctionne pour vous sur ces fronts, je courrais avec. Nous avons écrit notre propre serveur de journaux de mise en mémoire tampon qui écrit dans des fichiers personnalisés et a ensuite un programme d'analyse séparé pour le lire dans une base de données pour les requêtes, je ne le recommanderais pas.


0

Les bases de données relationnelles sont de nos jours jugées inefficaces, mais lorsque vous stockez le type de journaux dont vous parlez, vous n'avez pas vraiment besoin d'efficacité car ils ne seront pas constamment consultés par le jeu ou ses utilisateurs - seule votre équipe aura besoin pour lire les données.

Donc, "l'efficacité" importe peu. Ce qui importe le plus, c'est de classer les données de manière à pouvoir raconter facilement ce que les utilisateurs font dans le jeu. Vos développeurs devront généralement consommer ces données et les afficher dans une interface facile à lire pour les analystes et les analystes devront parfois interroger les données pour approfondir le comportement des utilisateurs. Par exemple, si les joueurs achètent un certain article avant une mise à jour, mais cessent de l'acheter après une mise à jour, un analyste bénéficiera en écrivant certaines requêtes qui exposent certains chiffres sur le comportement entourant cet achat pour déterminer pourquoi les utilisateurs ne l'achètent plus. Il est préférable qu'ils aient un langage de requête standard avec lequel travailler est bien documenté. S'ils doivent transformer ces requêtes en un format binaire personnalisé, leurs tâches seront BEAUCOUP plus difficiles,

Généralement, les événements de jeu ressemblent à ceci (c'est le format de DeltaDNA en particulier)

{
 "eventName":"specific event code – eg. gameStarted",
 "userID":"ABCD1-4321a879b185fcb9c6ca27abc5387e914",
 "sessionID":"4879bf37-8566-46ce-9f3b-bd18d6ac614e",
 "eventTimestamp":"yyyy-mm-dd hh:mm:ss.SSS",
 "eventParams":
  {
   "platform":"WEB",
   "param1":"stringParam",
   "param2":true,
   "param3":1234,
   "param4":["a","b","c"]
  },
}

L'événement comprend généralement un nom d'événement, un ID utilisateur, un ID de session, un horodatage et des paramètres qui vous permettent d'enregistrer toutes les données que vous trouvez utiles pour enregistrer autour de cet événement. Et d'après mon expérience, les formats de bases de données relationnelles sont les meilleurs pour enregistrer une telle structure.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.