¿Cómo almacena mmorpg los datos?

22

Quiero usar la base de datos sql en mi server.exe.

digamos 1000 usuarios en línea. Y los jugadores cambiarán sus datos cuando jueguen. Y el servidor necesita guardar estas actualizaciones.

Pero cómo ?

Creo que hay dos maneras:

1) el servidor guardará en ram en tiempo de ejecución y el servidor en algún momento o por hora escribirá datos (actualización) en la base de datos sql desde ram. Pero si se va la electricidad o de alguna manera el servidor se apaga, las actualizaciones no se guardarán. Por supuesto que no quiero perder actualizaciones.

2) el servidor guardará las actualizaciones en la base de datos en tiempo de ejecución. ¿Pero qué pasará con la velocidad? Pensé en un método. Te mostraré a continuación con la imagen. ¿Puedo obtener suficiente velocidad para 1000 jugadores en línea con este método? ingrese la descripción de la imagen aquí

Emre Kaya
fuente
11
¿Has hecho alguna referencia? ¿Qué te hace pensar que las operaciones de la base de datos serían un problema para tu juego?
congusbongus
3
¿Si tu estado de juego es realmente relacional? ¿Estás seguro de que quieres una base de datos SQL?
Deja de dañar a Monica el
66
También lea cómo manejar las contraseñas utilizando hashes. O al menos notifique al usuario que su contraseña se está guardando como texto sin formato, para que sepa que no debe usar otra contraseña segura.
TomTsagk
24
Como nota al margen, si desea crear un MMO comercial y está haciendo preguntas como esta, probablemente debería comenzar con algo más pequeño. Los MMO son increíblemente difíciles de hacer, y mucho menos hacerlo bien, y no son tan buenos desde el punto de vista comercial. Si esto es solo algo personal y desea aumentar el conteo de jugadores, comience con algo así como 64 jugadores, luego vaya ascendiendo. Será mucho más fácil que tratar de diseñar la arquitectura "perfecta" desde cero sin experiencia. Mira esto .
Financia la demanda de Mónica el
1
Puede escribir una API general que sea independiente del almacenamiento. Luego escriba un adaptador que guarde en caché los datos en la RAM para el almacenamiento retrasado. O puede escribir un adaptador que almacena datos en caché en un archivo temporal antes de vaciarlo en SQL DB. De esa manera, puede activar y desactivar el almacenamiento en caché para averiguar cuál es el mejor. No necesita escribir código extra demasiado, si su arquitectura está construida correctamente.
0xC0DEGURU

Respuestas:

37

La mayoría de los MMO (o proyectos que usan una arquitectura similar) en los que he trabajado o sé que usan el primer método: los servidores de juegos funcionan principalmente con la RAM en las máquinas que ejecutan los procesos del servidor, y solo serializan periódicamente los datos relevantes del juego en una base de datos SQL para el archivo (si se usa alguno).

Los problemas que observa con respecto a la falla de energía son válidos, pero menos probables que problemas como fallas en el proceso (la confiabilidad del tiempo de actividad generalmente es una de esas cosas por las que pagaría el centro de datos). Pero aún. Puede mitigar esos problemas a través de cosas como ajustar el intervalo de guardado (por lo que una falla solo cuesta a lo sumo unos pocos minutos de progreso), distribuir las colas de guardado en varias máquinas, definir agresivamente la cantidad de datos que deben guardarse e implementar guardar reiniciable colas

En términos generales, el uso del servidor SQL como memoria principal será desagradablemente lento (y engorroso). No veo suficientes detalles en su propuesta para poder decir con certeza si funcionaría solo para unos 1000 jugadores, probablemente estaría bien. Pero no creo que puedas hacerlo agresivamente escalable.

Además, no resuelve el problema. Una falla de energía durante el proceso de guardado aún perderá o corromperá los datos a menos que haga el trabajo para implementar el mismo tipo de cola de guardado reiniciable (que incluso entonces, eso solo reduce severamente la probabilidad de pérdida de datos catastrófica, no lo evita) .

Te recomiendo que vayas con el primer enfoque.


fuente
10
Con respecto a "ajustar el intervalo de guardado", el último MMO en el que trabajé tenía un intervalo de guardado basado en el número de jugadores activos. Sabíamos que podía manejar el almacenamiento de datos de X jugadores por segundo sin un cuello de botella notable, por lo que simplemente ahorramos un poco menos de X jugadores por segundo de forma rotativa. Por lo general, terminó siendo un ahorro para cada jugador cada dos minutos más o menos en los días ocupados, y tal vez dos veces por minuto durante los tiempos lentos.
Meanbits
44
¿"Cola de guardado reiniciable" suena como un diario, como lo implementan muchos sistemas de archivos y motores de bases de datos?
Grawity
66
Estos problemas no son exclusivos de los MMO, o incluso juegos de vídeo, en absoluto . Casi todos los ORM existentes ofrecen algún tipo de mecanismo de almacenamiento en caché / procesamiento por lotes. No hay necesidad de lanzar su propia solución.
BlueRaja - Danny Pflughoeft
3
Si termina guardando en un disco en un intervalo determinado, le recomiendo diseñar un sistema donde las cosas se puedan guardar de inmediato, para cuando las personas obtienen una rara caída / dado / etc. De esa manera, si hay un bloqueo del servidor o algo así, las personas que lograron algo grande no se molestarán demasiado.
Jon
55
@ Jon, y luego te encuentras con el problema de que las personas puedan duplicar objetos. Lo ideal es que guarde todo el estado del juego periódicamente como una sola transacción. Una vez que comience a guardar por partes, terminará en situaciones en las que un bloqueo puede causar datos inconsistentes; los jugadores que pueden provocar un bloqueo a pedido, o incluso predecir cuándo es probable que ocurra un bloqueo, pueden aprovechar esto para su ventaja.
Mark
15

1000 jugadores pueden o no ser un problema. Depende de la frecuencia con la que necesite actualizar la base de datos. Sin embargo, hay una solución simple: poner la base de datos en su propio servidor.


Eché un vistazo a cómo funciona el sistema de base de datos en un juego que la gente llamaría un MMO-Lite, que no revelaré, pero puedo decir que consistentemente tiene más de 1000 jugadores, este es el resumen:

  • Utilizan una base de datos "No-SQL" basada en documentos para obtener información de carácter privado (inventario, equipo, similar).
  • Utilizan una base de datos relacional más tradicional para la información de carácter público que rara vez se actualiza (nombre, logros, etc.) y estadísticas.

El uso de una base de datos basada en documentos resulta ser una buena idea para el rendimiento en este caso. Es bueno para acceder a los datos, aunque es malo para hacer uniones y agregaciones ... pero no lo harán con los datos que están allí.

Por otro lado, cuando necesitan hacer algo como cambiar un objeto con otro objeto para todos, la necesidad de ejecutar un script de fondo que vaya carácter por carácter y los actualice uno por uno, lleva un tiempo notable.


Los datos del personaje existen tanto en el cliente como en el servidor, y el sistema está diseñado para mantenerlos sincronizados, realizando las mismas operaciones en ambos lados.

Ahora, cuando un jugador realiza una transacción con el sistema, por ejemplo, cambiar un artículo por otro a través de un NPC o similar, esto tiene estas etapas:

  • El cliente comprueba si la operación es válida.
  • El cliente envía la operación al servidor (operación asíncrona)
  • El cliente actualiza su modelo en RAM
  • El servidor comprueba si la operación es válida.
  • El servidor actualiza su modelo en RAM
  • El servidor actualiza la base de datos (operación asincrónica)
  • El servidor le dice al cliente que el cambio ocurrió

Notas :

  • Las actualizaciones de la base de datos, aunque asíncronas, se realizan de inmediato. Si por alguna razón el servidor del juego se cae, no se pierde mucho.
  • La degradación del rendimiento no es gran cosa gracias a colocar las bases de datos en sus propios servidores.

Los intercambios entre jugadores se manejan de manera similar, con reglas adicionales para evitar que los jugadores engañen a otros jugadores, y una trazabilidad adicional en caso de que una transacción deba deshacerse. Escuché que hay registros especiales de todas las transacciones que se guardan durante un tiempo (para resolver problemas cuando alguien se queja), no sé más sobre cómo funciona esa parte.


A veces algo sale mal, esto tiene dos resultados posibles:

  • Si el error ocurre de inmediato, el servidor le dirá al cliente, que revertirá la operación (el jugador ve que la operación se ha deshecho).
  • La interfaz de usuario dice que el jugador tiene un elemento, pero el servidor no está de acuerdo. Si el usuario intenta usarlo, le preguntará al servidor y fallará, dejando inutilizable el objeto falso. El objeto falso desaparece cuando se vuelve a cargar el inventario, que se utiliza como una oportunidad para sincronizar el modelo.

En cualquier caso, el cliente es consciente del error y lo registrará junto con todo lo que el jugador estaba haciendo. El registro del lado del cliente ocurre todo el tiempo. Luego, al cerrar sesión, si hubo un error, el cliente envía los registros al servidor.


Este juego no utiliza el tradicional tiempo de inactividad de mantenimiento diario o semanal que tiene la mayoría de los MMORPG. Ese mantenimiento programado se usa a menudo para restablecer contadores, temporizadores, ejecutar procedimientos de base de datos. También son la oportunidad de intercambiar versiones del servidor por una actualización.

Theraot
fuente
Gracias, pero ¿qué pasa con los jugadores de los movimientos por ejemplo, si un jugador se mueve de su posición actual: x:10,y:10,z:10Para x:11,y:11,z:11, si ello se guardan en la base de datos de inmediato? qué pasa si el jugador sigue corriendo, esto significa que guardamos su posición actual cada 1 segundo o menos, y si hay miles de jugadores, son millones de consultas a la base de datos cada segundo. Así es como funciona ?
dwix
2
La posición del jugador debe guardarse muy raramente en la base de datos. Solo querrás eso en ocasiones especiales como abrir el menú, comenzar una fogata, descansar, etc. Dependiendo del juego, ni siquiera se guardará tan detalladamente. Algunos juegos siempre te hacen engendrar en la ciudad más cercana, etc., por lo que también ahorrarías la molestia de guardar la posición. Pero eso deriva en una opinión basada.
Nico
1
@dwix en el caso del juego del que hablo, la posición del jugador ni siquiera se guarda. Si cierra sesión e inicia sesión, o si el servidor se cae, el jugador volverá a estar en una posición segura conocida (editar: es una instancia privada, "casa" si lo desea, pero es lo mismo para todos). Sin embargo, algunos juegos mantienen la posición exacta del jugador, incluso en caso de desconexión accidental. Para hacerlo, el enfoque habitual es almacenar esa información con menos frecuencia. De todos modos, no hace lo que el servidor espera en la base de datos.
Theraot
1
@dwix cuando se habla de la posición del avatar, realmente no te importan los valores históricos, ¿verdad? Bueno, si la base de datos es un cuello de botella, entonces estrangule los datos. En lugar de almacenar cada marca de servidor, almacene con menos frecuencia. Significa que la base de datos no tendrá el valor más actualizado, pero no afectará tanto el rendimiento. Mientras tanto, el servidor seguirá manteniendo el valor de actualización en RAM, y eso es con lo que funciona. Anexo: honestamente, recomendaría no almacenar las posiciones, pero algunos juegos lo hacen.
Theraot
1
@dwix ver comentario de meanbits
Theraot
7

Ambos enfoques se utilizan con MMORPG. Mantener todo en la memoria y verificar periódicamente apuntarlo al disco parece ser la opción más popular, al menos para los juegos más antiguos. Tiene la ventaja de ser bastante simple de implementar y escalar bastante bien, pero hacer que sea confiable depende completamente del desarrollador. Las bases de datos SQL proporcionan propiedades ACID que facilitan la confiabilidad, pero en general son más complicadas de implementar bien y pueden tener problemas con el escalado.

EVE Online es un ejemplo de un MMO donde todo se almacena en una base de datos SQL. Creo que alcanzó su punto máximo en alrededor de 60,000 usuarios simultáneos, y ha tenido que dedicar un hardware costoso a los servidores de bases de datos a lo largo de los años para mantenerse al día con la carga. Sin embargo, EVE almacena muchos más datos por usuario que la mayoría de los MMORPG y tiene transacciones mucho más frecuentes y variadas. Las propiedades ACID de la base de datos permiten que toda la base de datos masiva y complicada se mantenga siempre en un estado coherente.

Por ejemplo, considere el caso cuando alguien le da un artículo a otro jugador. La base de datos de EVE garantiza que incluso en el caso de un choque o falla de energía, el artículo termina en el inventario de un solo jugador. Es decir, la transacción de la base de datos que elimina el artículo del inventario de un jugador y lo agrega al del otro jugador es atómica. La transacción se completa por completo o no ocurre en absoluto. No puedes terminar en un estado donde el objeto existe en el inventario de ninguno de los jugadores o en ambos.

Un MMORPG que mantiene los datos del jugador en la memoria y los puntos de control periódicamente tiene que implementar esta atomicidad. Una forma de hacer esto sería el punto de control de los datos de cada jugador al mismo tiempo, asegurando que el nuevo punto de control esté completamente comprometido con el disco antes de que se considere el punto de control más reciente. El juego también debería garantizar que los datos del jugador no puedan cambiar mientras se controlan. Con una gran cantidad de jugadores activos, el desafío se convierte en hacer todo esto sin causar un retraso lo suficiente como para que los jugadores lo noten.

No subestimes lo importante que es la consistencia. Cuando desarrolles tu juego, se bloqueará mucho. No querrás tener que rastrear por qué los elementos desaparecen y / o se duplican, no cuando el problema es un error no relacionado que hace que el juego se bloquee en un mal momento. Además, cuando tu juego se active, se bloqueará mucho más de lo que esperas. Su servidor que funcionaba perfectamente bajo pruebas, de repente expondrá numerosos errores bajo carga completa y los jugadores harán cosas que no esperaba.

Tenga en cuenta que la mayoría de los MMORPG usan bases de datos SQL para la información relacionada con la cuenta, incluso si no lo hacen para los datos reales del juego. Incluso más importante que mantener el estado del juego en un estado consistente es mantener el estado de facturación consistente. El peor caso para que la base de datos del juego se corrompa es que debe restaurar la base de datos a partir de una copia de seguridad diaria. El peor caso para que la base de datos de la cuenta se corrompa es que vaya a la quiebra debido a todas las devoluciones de cargo.

Para su proyecto, probablemente pueda ir en cualquier dirección. Tener 1000 usuarios simultáneos probablemente no superará los límites de lo que un servidor SQL puede manejar en una PC común en estos días, pero mucho dependerá de la naturaleza de las transacciones. Si está familiarizado con SQL y el diseño de bases de datos relacionales, esto puede funcionar para usted. Querrá minimizar las transacciones tanto como sea posible, para algo como los puntos de vida actuales del jugador, es posible que solo desee guardarlos periódicamente en la base de datos, ya que estadísticas como estas no necesariamente tienen que ser consistentes. (Sin embargo, en el juego PvP podrían ...) No almacene cosas como HP monstruoso en la base de datos, en la mayoría de los juegos solo los datos relacionados con el jugador son persistentes.

Por otro lado, si no eres un asistente de SQL, es posible que mantener todos los datos en la memoria sea mucho más simple para que funcione de manera confiable. Las bases de datos SQL facilitan la coherencia y la fiabilidad, pero no son automáticas. Una base de datos mal diseñada puede funcionar mal y generar inconsistencias. Las transacciones no serán atómicas a menos que lo haga. Si no usa declaraciones parametrizadas religiosamente, se abrirá a los ataques de inyección SQL.

Ross Ridge
fuente
0

Varios juegos almacenan cosas de diferentes maneras. A menudo, las compañías de juegos crean alguna forma de hacer esto, y la mayoría de sus juegos usan de la misma manera. Por supuesto, diferentes estudios a menudo usan diferentes formas. SQL ciertamente se usa para juegos, por ejemplo, CCP (EVE) tiene (o al menos ha tenido) una red de servidores SQL, no estoy seguro de cómo lo hacen ahora. Otros, solo usan muchos archivos.

¿Quizás comenzar creando un "mecanismo de agente de datos" agnóstico para manejar varias transacciones de datos del juego? Como de todas formas solo estás probando, crea un mecanismo que te permita no tener que preocuparte demasiado por el almacenamiento, desde el punto de vista del juego en sí. Es decir, concéntrese en cómo, desde la aplicación host, va a manejar esto.

Personalmente, creo que sería una gran ventaja si pudieras cambiar la tienda real, sin tener que volver a escribir el juego y el corredor en sí. Simplemente cambie a otro módulo con la misma interfaz para que el corredor pueda hablar.

El almacenamiento de datos en sí mismo probablemente no será un problema, per se. El envío eficiente de datos, a / desde esa tienda, entre el host y todos los clientes, podría ser más complicado. ¿Envío todo el conjunto de datos del reproductor, o si lo desgloso en partes, qué granularidad elijo para dividir, etc. Cuál es más intensivo en recursos en qué situación, etc.

Un formato para enviar los datos podría ser XML. De esa manera, puede ser más dinámico en cuanto a cómo puede dividirlo. Un carácter frente a varios caracteres, o un elemento frente a una colección de elementos, etc. A continuación, puede "almacenar" el XML como XML (en SQL) y / o hacer que SQL lo distribuya de una manera más transaccional desde el XML, hasta cómo quiere que se almacenen los datos.

Otra forma es binaria, que es más eficiente en términos de envío, pero puede generar más costos en otras situaciones.

Con 1,000 clientes, puede comenzar y almacenar fácilmente 10 MB por cliente y solo usar 10 GB de RAM efectiva + agregar algo de RAM administrativa del sistema para administrar esos datos, digamos otros GB o dos. Puede mantener eso en la RAM del host que ya está en la estructura de datos lista para usar. Y cargue / guarde dinámicamente, dependiendo de quién esté en línea, en varias frecuencias dependiendo de la actividad, etc.

Incluso podría almacenar la información de cada cliente en un archivo separado, y así sucesivamente.

Robar
fuente
0

Mantenga los jugadores * en línea * en ram y empújelos a una base de datos (SQLite? MySQL?) Cuando cierren sesión. si te preocupa que IO se bloquee durante el cierre de sesión, dale a cada cierre de sesión su propio hilo, no lo hagas en el hilo principal / del juego (en realidad mantengo un hilo de jugador dedicado para cada jugador en línea, hizo que el código de red fuera mucho más fácil que hacer el enfoque asincrónico de red io)

Hanshenrik
fuente