Как mmorpg хранит данные?

22

Я хочу использовать базу данных sql в моем server.exe.

скажем, 1000 пользователей онлайн. И игроки будут менять свои данные, когда они играют. И на сервере нужно сохранить эти обновления.

Но как ?

я думаю, что есть два пути:

1) сервер будет сохранять в оперативной памяти во время выполнения, а иногда или ежечасно сервер будет записывать данные (обновление) в базу данных sql из оперативной памяти. Но если электричество отключится или сервер отключится, обновления не сохранятся. Конечно, я не хочу терять обновления.

2) сервер будет сохранять обновления в базе данных во время выполнения. но что будет со скоростью? Я думал о методе. Я покажу вам ниже с изображением. Могу ли я получить достаточную скорость для 1000 игроков онлайн с помощью этого метода? введите описание изображения здесь

Эмре Кая
источник
11
Вы сделали какие-либо тесты? Что заставляет вас думать, что операции с базой данных будут проблемой для вашей игры?
congusbongus
3
Если ваше игровое состояние на самом деле реляционное? Вы уверены, что хотите базу данных SQL?
Стоп Harm Моника
6
Также, пожалуйста, прочитайте, как обрабатывать пароли с помощью хэшей. Или, по крайней мере, уведомите пользователя о том, что его пароль сохраняется в виде простого текста, чтобы он знал, что не следует использовать другой безопасный пароль.
ТомЦагк
24
В качестве примечания: если вы хотите создать коммерческую MMO и задаете такие вопросы, вам, вероятно, следует начать с чего-то меньшего. ММО невероятно сложно сделать вообще, не говоря уже о том, чтобы делать их правильно, и они не так уж хороши с точки зрения бизнеса. Если это просто личное дело, и вы хотите увеличить количество игроков, начните с чего-то вроде 64 игроков, а затем поднимитесь. Это будет намного проще, чем пытаться создать «идеальную» архитектуру с нуля без опыта. Смотрите это .
Фонд Моника иск
1
Вы можете написать общий API, который не зависит от хранилища. Затем напишите адаптер, который кэширует данные в оперативной памяти для отложенного хранения. Или вы можете написать адаптер, который кэширует данные во временном файле, прежде чем сбрасывать их в базу данных SQL. Таким образом, вы можете включать и выключать кэширование, чтобы узнать, что лучше. Вам не нужно писать слишком много лишнего кода, если ваша архитектура построена правильно.
0xC0DEGURU

Ответы:

37

Большинство ММО (или проектов, использующих подобную архитектуру), над которыми я работал или знаю, используют первый метод: игровые серверы работают в основном с ОЗУ на машинах, на которых выполняются серверные процессы, и только периодически сериализуют соответствующие игровые данные в базу данных SQL. для архивирования (если он вообще используется).

Проблемы, с которыми вы сталкиваетесь при сбое питания, действительны, но менее вероятны, чем такие, как сбои в процессе (надежность времени безотказной работы, как правило, является одной из тех вещей, за которые вы платите центру обработки данных). Но до сих пор. Вы устраняете эти проблемы с помощью таких настроек, как настройка интервала сохранения (таким образом, сбой стоит всего несколько минут), распределение очередей сохранения по нескольким машинам, агрессивное определение объема данных, которые необходимо сохранить, и внедрение перезапускаемого сохранения. очереди.

Вообще говоря, использование самого SQL-сервера в качестве основной памяти будет неприятно медленным (и громоздким). Я не вижу достаточно подробностей в вашем предложении, чтобы можно было с уверенностью сказать, сработает ли это только для 1000 игроков - это, вероятно, будет хорошо. Но я не верю, что вы можете сделать это агрессивно масштабируемым.

Кроме того, это не решает проблему. Сбой питания во время процесса сохранения все равно приведет к потере или повреждению данных, если вы не выполните работу по реализации перезапускаемой очереди сохранения того же типа (которая даже тогда, которая лишь значительно снижает вероятность катастрофической потери данных, не предотвращает ее) ,

Я бы порекомендовал вам пойти с первого подхода.


источник
10
Что касается «настройки интервала сохранения», у последней MMO, над которой я работал, был интервал сохранения, основанный на количестве активных игроков. Мы знали, что он может справиться с сохранением данных X игроков в секунду без заметного узкого места, поэтому мы просто сохранили немного меньше X игроков в секунду на ротационной основе. Обычно это заканчивалось спасением для каждого игрока каждые две минуты или около того в напряженные дни и, может быть, два раза в минуту в медленное время.
Подлое
4
«Перезапускаемая очередь сохранения» звучит как журнал, как это реализовано многими файловыми системами и механизмами баз данных?
Гравитация
6
Эти проблемы не являются уникальными для НММ, или даже видеоигр, на всех . Почти каждый существующий ORM обеспечивает своего рода механизм кэширования / пакетирования. Там нет необходимости катить свое собственное решение.
BlueRaja - Дэнни Пфлюгофт
3
Если вы в конечном итоге продолжите сохранение на диск с определенным интервалом, я бы порекомендовал разработать систему, в которой вещи можно было бы сохранить немедленно, на случай, если люди получат редкое падение / смерть / и т.д. Таким образом, если произойдет сбой сервера или что-то еще, люди, достигшие чего-то большого, не будут слишком расстроены.
Джон
5
@Jon, а затем вы сталкиваетесь с проблемой людей, способных дублировать объекты. В идеале вы должны периодически сохранять все состояние игры как одну транзакцию. Как только вы начинаете сохранение по кусочкам, вы попадаете в ситуации, когда сбой может привести к несогласованности данных; игроки, которые могут вызвать сбой по требованию или даже предсказать, когда сбой может произойти, могут использовать это в своих интересах.
Марк
15

1000 игроков может или не может быть проблемой. Это зависит от того, как часто вам нужно обновлять базу данных. Однако есть простое решение: разместить базу данных на своем собственном сервере.


Я взглянул на то, как система баз данных работает в игре, которую люди назвали бы MMO-Lite - которую я не буду раскрывать, - но я могу сказать, что в ней постоянно более 1000 игроков, это реферат:

  • Они используют базу данных No-SQL на основе документов для личной информации о персонажах (инвентарь, оборудование и т. П.).
  • Они используют более традиционную реляционную базу данных для общедоступной символьной информации, которая редко обновляется (имя, достижения и т. Д.) И статистики.

Использование базы данных на основе документов оказывается хорошей идеей для производительности в этом случае. Это хорошо для доступа к данным, хотя это плохо для выполнения объединений и агрегаций ... но они не будут делать это с данными, которые там находятся.

С другой стороны, когда им нужно сделать что-то, например, заменить объект другим объектом для всех, необходимость запустить фоновый скрипт, который идет символ за символом и обновляет их один за другим, это занимает заметное время.


Данные персонажа существуют как на клиенте, так и на сервере, и система предназначена для их синхронизации, выполняя одинаковые операции с обеих сторон.

Теперь, когда игрок совершает транзакцию с системой, скажем, обменивает предмет на другого через NPC или подобное - это имеет следующие стадии:

  • Клиент проверяет, действительна ли операция
  • Клиент отправляет операцию на сервер (асинхронная операция)
  • Клиент обновляет свою модель в оперативной памяти
  • Сервер проверяет, действительна ли операция
  • Сервер обновляет свою модель в оперативной памяти
  • Сервер обновляет базу данных (асинхронная операция)
  • Сервер сообщает клиенту, что изменение произошло

Примечания :

  • Обновления базы данных, хотя и асинхронные, выполняются сразу же. Если по какой-либо причине игровой сервер выходит из строя, мало что теряется.
  • Снижение производительности не имеет большого значения благодаря размещению баз данных на собственных серверах.

Сделки между игроками обрабатываются аналогично, с дополнительными правилами, предотвращающими мошенничество игроков с другими игроками, и дополнительным отслеживаемостью в случае необходимости отмены транзакции. Я слышал, что есть специальные журналы всех транзакций, которые хранятся в течение некоторого времени (для решения проблем, когда кто-то жалуется), я не знаю больше, как эта часть работает.


Иногда что-то идет не так, у этого есть два возможных результата:

  • Если ошибка происходит сразу же, сервер сообщит клиенту, что вернет операцию (игрок видит, что операция отменена).
  • Пользовательский интерфейс говорит, что у игрока есть предмет, но сервер не соглашается. Если пользователь попытается использовать его, он запросит сервер и потерпит неудачу, делая поддельный объект непригодным для использования. Ложный объект исчезает при перезагрузке инвентаря, который используется как возможность для синхронизации модели.

В любом случае клиент знает об ошибке и регистрирует ее вместе со всем, что делал игрок. Ведение журнала на стороне клиента происходит постоянно. Затем при выходе из системы, если произошла ошибка, клиент отправляет журналы на сервер.


Эта игра не использует традиционное ежедневное или еженедельное время простоя обслуживания, которое есть у большинства MMORPG. Это плановое обслуживание часто используется для сброса счетчиков, таймеров, запуска процедур базы данных. Они также дают возможность поменять версии сервера для обновления.

Theraot
источник
Спасибо, но как насчет движений игрока, например, если игрок перемещается из своей текущей позиции: x:10,y:10,z:10Кому x:11,y:11,z:11, это должно быть сохранено в базе данных сразу? Что если игрок продолжает работать, это означает, что мы сохраняем его текущую позицию каждые 1 с или менее, а если есть тысячи игроков, это миллионы запросов к БД каждую секунду. Это как это работает?
Дв
2
Положение игрока должно быть сохранено очень редко в базе данных. Вы хотели бы этого только в особых случаях, таких как открытие меню, запуск походного костра, отдых и т. Д. В зависимости от игры даже не будет сохранено это подробное описание. В некоторых играх вы всегда появляетесь в ближайшем городе и т. Д., Так что это избавляет от хлопот, связанных с сохранением позиции. Но это дрейфует на основе мнения.
Нико
1
@dwix в случае игры, о которой я говорю, положение игрока даже не сохраняется. Если вы выйдете из системы и войдете в систему, или если сервер выйдет из строя, игрок вернется в безопасное известное положение (правка: это частный экземпляр, «дом», если хотите, но он одинаков для всех). Тем не менее, некоторые игры сохраняют точное положение игрока даже при случайном отключении. Чтобы сделать это, обычный подход - хранить эту информацию реже. Независимо от того, вы не то, что сервер ждет в базе данных.
Theraot
1
@dwix, когда говоришь о положении аватара, тебя не волнуют исторические ценности, не так ли? Что ж, если база данных - «бутылочная горлышко», тогда дросселируйте данные. Вместо того, чтобы хранить каждый тик сервера, сохраняйте реже. Это означает, что база данных не будет иметь самое актуальное значение, но это не будет так сильно влиять на производительность. Между тем сервер все равно будет хранить значение обновления в оперативной памяти, и именно с этим он работает. Приложение: честно говоря, я бы советовал не сохранять позиции, но некоторые игры делают это.
Theraot
1
@dwix см. комментарий подлых
Theraot
7

Оба подхода используются с MMORPG. Хранение всего в памяти и периодическая проверка наведения на диск кажется наиболее популярным вариантом, по крайней мере, для старых игр. Его преимущество в том, что он довольно прост в реализации и достаточно хорошо масштабируется, но сделать его надежным полностью зависит от разработчика. Базы данных SQL предоставляют свойства ACID, которые облегчают надежность, но в целом сложнее в реализации и могут иметь проблемы с масштабированием.

EVE Online - это пример MMO, где все хранится в базе данных SQL. Я думаю, что он достиг примерно 60000 одновременных пользователей, и ему пришлось выделять какое-то дорогостоящее оборудование для серверов баз данных на протяжении многих лет, чтобы не отставать от нагрузки. Однако EVE хранит намного больше данных на пользователя, чем большинство MMORPG, и имеет гораздо более частые и разнообразные транзакции. Свойства ACID базы данных позволяют поддерживать целостность всей массивной и сложной базы данных.

Например, рассмотрим случай, когда кто-то передает предмет другому игроку. База данных EVE гарантирует, что даже в случае сбоя или сбоя питания предмет попадет в инвентарь только одного игрока. То есть транзакция базы данных, которая удаляет элемент из инвентаря одного игрока и добавляет его в инвентарь другого игрока, является атомарной. Сделка либо полностью завершена, либо не происходит вообще. Вы не можете оказаться в состоянии, если предмет не существует ни в инвентаре игроков, ни в обоих.

MMORPG, которая хранит данные игрока в памяти и периодически проверяет, должна ли она сама реализовывать эту атомарность. Одним из способов сделать это будет одновременная проверка данных каждого игрока, гарантируя, что новая контрольная точка будет полностью зафиксирована на диске до того, как она будет считаться самой последней контрольной точкой. Игра также должна была бы гарантировать, что данные игрока не могут измениться во время проверки. С большим количеством активных игроков, задача становится делать все это, не вызывая задержки достаточно долго, чтобы игроки заметили.

Не стоит недооценивать, насколько важна последовательность. Когда вы разрабатываете свою игру, она очень часто падает. Вам не нужно отслеживать, почему предметы исчезают и / или дублируются, а не тогда, когда проблема связана с ошибкой, приводящей к аварийному завершению игры. Более того, когда ваша игра выйдет в эфир, она рухнет намного сильнее, чем вы ожидаете. Ваш сервер, который отлично работал при тестировании, неожиданно обнаружит многочисленные ошибки при полной нагрузке и действия игроков, о которых вы не ожидали.

Обратите внимание, что большинство MMORPG используют базы данных SQL для информации, связанной с учетной записью, даже если они не для реальных игровых данных. Еще более важным, чем сохранение состояния игры в согласованном состоянии, является поддержание согласованности состояния выставления счетов. В худшем случае, если база данных игры будет повреждена, вам придется восстанавливать базу данных из ежедневной резервной копии. В худшем случае, если база данных аккаунта будет повреждена, вы обанкротитесь из-за всех возвратных платежей.

Для вашего проекта вы можете пойти в любую сторону. 1000 одновременных пользователей, вероятно, не будут расширять границы возможностей, которые SQL-сервер может обрабатывать на обычных ПК в наши дни, но многое будет зависеть от характера транзакций. Если вы знакомы с SQL и проектированием реляционных баз данных, это может сработать для вас. Вы захотите свести к минимуму количество транзакций, насколько это возможно, для чего-то вроде текущих хитпоинтов игрока вы можете лишь периодически сохранять их в базе данных, поскольку подобная статистика не обязательно должна быть согласованной. (Хотя в PvP-игре они могут ...) Вообще не храните в базе данных такие вещи, как monster HP, в большинстве игр сохраняются только данные, относящиеся к игроку.

С другой стороны, если вы не являетесь мастером SQL, вам может показаться, что хранить все данные в памяти гораздо проще для надежной работы. Базы данных SQL упрощают согласованность и надежность, но не обеспечивают автоматическую работу. Плохо спроектированная база данных может работать плохо и приводить к несоответствиям. Транзакции не будут атомарными, если вы их не сделаете. Если вы не будете религиозно использовать параметризованные операторы, вы откроете себя для атак SQL-инъекций.

Росс Ридж
источник
0

Различные игры хранят вещи по-разному. Зачастую игровые компании создают какой-то способ сделать это, и большинство их игр используют один и тот же способ. Конечно, разные студии часто используют разные способы. SQL, безусловно, используется для игр, например, CCP (EVE) имеет (или, по крайней мере, имеет) сеть серверов SQL, я не уверен, как они это делают сейчас. Другие просто используют много файлов.

Может быть, начать с создания независимого «механизма брокера данных» для обработки различных транзакций с игровыми данными? Поскольку в любом случае вы просто тестируете, создайте механизм, который позволит вам не заботиться о хранилище с точки зрения самой игры. То есть сконцентрируйтесь на том, как из хост-приложения вы справитесь с этим.

Лично я думаю, что было бы очень полезно, если бы вы могли сменить магазин, не переписывая игру и самого брокера. Просто переключитесь на другой модуль с тем же интерфейсом, чтобы брокер мог с ним общаться.

Хранение данных само по себе, вероятно, не будет проблемой само по себе. Эффективная доставка данных в / из этого хранилища, между хостом и всеми клиентами, может быть сложнее. Должен ли я отправлять весь набор данных игрока, или если я разбиваю его на части, какую гранулярность я выбираю для разделения и т. Д. Какой из них более ресурсоемкий в какой ситуации и т. Д.

Одним из форматов отправки данных может быть XML. Таким образом, вы можете быть более динамичными в том, как вы можете разбить его на части. Один символ против нескольких символов, или один элемент против коллекции элементов и т. Д. Затем можно было бы либо «сохранить» XML как XML (в SQL), и / или заставить SQL распространять его более транзакционным способом из XML, чтобы как вы хотите данные на самом деле хранятся.

Другой способ - бинарный, более эффективный с точки зрения доставки, но в других ситуациях он может повлечь за собой большие затраты.

Имея 1000 клиентов, вы могли бы начать с простого хранения 10 МБ для каждого клиента и использовать только 10 ГБ оперативной памяти + добавить некоторую системную административную память для управления этими данными, скажем, еще один или два ГБ. Вы можете сохранить это в оперативной памяти на хосте, уже в структуре данных, готовой к использованию. И загружать / сохранять динамически, в зависимости от того, кто в сети, на разных частотах в зависимости от активности и т. Д.

Вы даже можете хранить информацию о каждом клиенте в отдельном файле и так далее.

обкрадывать
источник
0

Держите * online * игроков в оперативной памяти и отправляйте их в базу данных (SQLite? MySQL?), Когда они выходят из системы. если вас беспокоит остановка ввода-вывода во время выхода из системы, присвойте каждому выходу свой собственный поток, не делайте этого в главном / игровом потоке (на самом деле я оставляю выделенный поток для каждого онлайн-игрока, это значительно упростило сетевой код) чем делать асинхронный сетевой подход)

hanshenrik
источник