Есть ли способ сделать динамический мир, такой как MMORPG, горизонтально масштабируемым?

11

Представьте себе открытый мир с более чем 500 игроками, данные которых меняются со скоростью 20 обновлений / игрок / секунду. В прошлый раз, когда я работал в похожей MMORPG, он использовал SQL, так что, очевидно, он не мог все время запрашивать БД. Вместо этого он загружал все проигрыватели из БД в память как объекты C ++ и использовал их. То есть он масштабируется по вертикали. Можно ли вместо этого сделать этот сервер горизонтально масштабируемым? Существует ли база данных, предназначенная для поддержки такого количества обновлений одновременно?

MaiaVictor
источник
Почему вы хотите обновить игрока в базе данных 20 раз / секунду?
Balon
@ Балон, вот где я в замешательстве. Если я не обновлю его в базе данных, просто в памяти, то у меня будут разные состояния на разных машинах. Но я думаю, что у обновлений БД есть огромные накладные расходы, так что на самом деле это не сработает для такого количества обновлений?
MaiaVictor
2
Если вы действительно, действительно думаете, что различные машины (или даже процессы) нуждаются в обновлениях с частотой 20 Гц для сотен объектов, тогда полностью обойдите базу данных и напрямую используйте систему обмена сообщениями. Но то, что вы действительно, действительно думаете, что хотите, это не то, что вы действительно хотите. То, что вы хотите, - это иметь разумный кругозор, который должен знать, что именно, а затем иметь способ аккуратно транспортировать объекты между областями действия поверх этого. Вы должны ответить на вопрос, почему вам нужны 20 Гц обновления между различными машинами для получения отличных ответов, кто-то может придумать новый способ взглянуть на проблему.
Патрик Хьюз
@PatrickHughes Я не знаю, что мне нужно, я просто объясняю, как работает игра. Персонажи перемещаются на 2 ~ 3 плитки в секунду. Охота на игрока может быть окружена несколькими монстрами, так что, по крайней мере, 10 плиток / игрок / секунду. Тогда есть предметы, разлагающиеся на полу, на рюкзаке игрока. Есть атаки, движущиеся в направлении игрока, есть атаки, движущиеся в направлении монстра. Есть ухудшение здоровья, использование маны, таймеры, наносящие урон ядом игроку. Итак, все меняется очень быстро. Это игровой дизайн. Как такой дизайн можно масштабировать по вертикали?
MaiaVictor
1
Я видел это на HackerNews некоторое время назад: paralleluniverse.co. Они работают над базой данных, которая выполняет всю работу по пространственной сегментации / распределению для вас. Я предполагаю, что под капотом они делают все, что в ответах ниже.
буксиры

Ответы:

17

Тестовый случай с участием 500 игроков, это 250 тыс. Потоков информации, летающих с частотой 20 Гц. Для этого внутренняя полоса пропускания, при условии, что каждое сообщение составляет 100 байт, составляет около 500 МБ / с. Звучит амбициозно. Особенно между процессами.

Если вы разделили игроков на группы по 100, это снизит до 20 МБ / с и так далее. Вот почему у ММО есть зоны, и в этих зонах мало пузырьков влияния и так далее вниз, пока пропускная способность не станет разумной.

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

Не используйте базу данных для общения, вот для чего нужен обмен сообщениями. Используйте базу данных для обеспечения транзакций и хранения информации, которую игроки не потеряют. Большинство ММО, с которыми я знаком, обновляют базу данных динамической информацией об игроке каждые 1-10 минут или в удобных точках, таких как переходы зон или вход в «безопасные» зоны в дизайне.

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

Также измените шаблон обновления с 20 Гц на скорость, основанную на расстоянии, кому-то на расстоянии в 1 милю не нужно знать, что вы переместились на 1 фут точно с 230,6 секундами, затем с другой ногой на 231,4 секунды, они могут справиться с тем, что вы двигаетесь на 15 футов каждые 10 секунд. секунд.

Патрик Хьюз
источник
Обалденный и информативный ответ, спасибо. Но я могу добавить, что, хотя мир меняется очень быстрыми темпами, игрок может видеть только других игроков, которые находятся рядом с ним. Я не считаю это геометрическим - 500 игроков отправляют информацию на сервер; Сервер периодически отправляет информацию этим 500 игрокам. Это линейно, как я вижу. Но главное в четвертом абзаце: если я использую базу данных только для хранения, я загружаю данные в память. Если я загружаю данные в память на машине, я создаю десинхронизированную версию мира. Вот чего я не понимаю.
MaiaVictor
Для 1 клиента: 1 выходное сообщение + 1 входное сообщение = 2. Для 2 клиентов: 2 выходное сообщение, 2 входное сообщение = 4. Для 3 клиентов: 3 выходное сообщение, 3 входное сообщение = 9. И так далее. Это примерно так: отправьте сообщение о состоянии, сервер отправит результат мне и двум другим клиентам (1 вход, 3 выхода) и 3 клиентам (1 из 9). Хотя это выглядит линейно только для одного клиента из трех, вы можете умножить это на всех клиентов для общей пропускной способности системы. Что касается десинхронизации, то даже процессы в одном и том же физическом блоке не синхронизированы до тех пор, пока сообщение о состоянии не будет создано и отправлено, это просто вопрос того, где канал очищается: локальная память или сеть.
Патрик Хьюз
5

Использовать фильтрацию областей интересов. Если мир разбит на 3 сервера, а область на сервере 1 находится далеко от области сервера 3, у них нет никаких оснований делиться информацией об объектах вообще.

Аналогично, на одном сервере отправляйте только соответствующую информацию клиентам. Если игрок A находится на совершенно противоположном конце карты от игрока B, то нет никаких оснований отправлять обновления о B в A или наоборот.

Когда у вас есть несколько серверов в непрерывном мире, у вас будут сущности рядом с краем на сервере 2, которые близки к сущностям на сервере 1. Вы можете отправлять обновления с «авторитетного» сервера для сущности на другой сервер (при необходимости) и аналогичным образом пересылать любые сообщения уполномоченному серверу в зависимости от ситуации.

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

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

Например, если сущность A атакует сущность B, не проверяет жизнь B, а затем отправляет сообщение о смерти, если оно достигает 0. Просто отправьте «поврежденное» сообщение, пусть уполномоченный сервер для B обработает его, а затем обработает любой сообщение «объект умер», отправленное сервером B позже, если объект A заботится об этом.

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

Шон Миддледич
источник
Спасибо, это положило конец большинству моих оставшихся сомнений. Также вы дали мне идею разделить серверы по игрокам, а не по областям - это выглядело бы более гладко. Каждый сервер заботится о х игроков. Мне действительно это нравится! Это используется? А еще есть еще одна вещь. Как я уже говорил выше, я только что узнал о новой базе данных NoSQL, Couchbase. Он должен быть похож на CouchDB, за исключением очень высокой скорости записи / чтения: до 200 тыс. Обновлений в секунду! Может быть, это действительно может работать в качестве такой «модели общего мира в реальном времени» или нет?
MaiaVictor
Я понятия не имею, используется ли эта техника в дикой природе, кроме обычного грубого «разбиения» серверов. Простое выполнение игроками и географической областью означает, что каждому серверу может потребоваться информация об очень большом количестве объектов в различных областях, что увеличивает нагрузку на сервер и значительно увеличивает межсерверную связь. Выполнение этого по областям означает, что ваш сервер может быть перегружен в многолюдных областях (хотя в этом случае вы можете динамически разделять и объединять области), но это означает, что каждый сервер имеет меньший набор соответствующих неигровых объектов и геометрии, чтобы отслеживать ,
Шон Миддледич
@Dokkat: может быть возможно иметь какие-то «мягкие области», где каждый сервер в основном обслуживает игроков в определенной части игрового мира, но позволяет им прозрачно передавать игрока на другой сервер, если они отклоняются слишком далеко от регион их оригинального сервера. Вам просто нужно убедиться, что передача достаточно гладкая, чтобы игроки не замечали этого. Вы могли бы даже попытаться использовать некоторые причудливые адаптивные методы, чтобы кластеры взаимодействующих игроков на одном сервере, даже если они находятся на границе региона.
Ильмари Каронен,
3

Возможно, вам будет интересна эта статья о Gamasutra , где разработчики Eve Online обсуждают, как можно успешно запустить игру с 400 000 активных игроков ... в одной базе данных SQL.

Liosan
источник
2

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

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

Фактическое состояние мира в реальном времени должно храниться игровыми серверами в памяти, как в вашем первоначальном примере. Уловка горизонтального масштабирования заключается в том, что не каждый сервер должен знать все в любой момент . Например, если игрок A играет в зоне A на сервере A, серверу B, управляющему зоной B, обычно не нужно знать, что у игрока A в рюкзаке - и, если это так , по какой-то причине нужно (например, поскольку игрок B в зоне B накладывает на А какое-то заклинание удаленного шпионажа, он может просто запросить эту информацию у другого сервера .

Для этого требуется, чтобы вы четко распределяли обязанности между серверами, поэтому, когда сервер B хочет узнать о рюкзаке игрока A, он будет знать, какой сервер имеет на нем достоверную информацию. Вы также , вероятно , захотите включить какой - то механизм подписки обновления, так что , например , сервер B может просто сказать сервера А « у меня есть кто - то шпионит игрока А, держать меня в курсе обо всем , что они делают , пока я не скажу иначе. » Вы, вероятно , также хотите включить какую-то глобальную систему вещания для важных глобальных событий, о которых игрокам, возможно, потребуется знать, где бы они ни находились; Конечно, такие события также должны регистрироваться в базе данных, но их активная широковещательная рассылка на все серверы означает, что серверам не нужно будет опрашивать базу данных на предмет обновлений.

Илмари Каронен
источник
Отличный ответ! Это было именно то, что я спрашивал, спасибо. Так что, возможно, ключ состоит в том, чтобы разделить сервер на зоны, сохраняя логику в оперативной памяти. Могу добавить, однако: я только что узнал о новой базе данных NoSQL, Couchbase. Он должен быть похож на CouchDB, за исключением очень высокой скорости записи / чтения: до 200 тыс. Обновлений в секунду! Может быть, это действительно может работать в качестве такой «модели общего мира в реальном времени» или нет?
MaiaVictor
@ Докат нет, не будет. Couchbase не волшебство.
Филипп
2

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

  • Точное местоположение в реальном времени может быть полезным в радиусе R
  • Менее точные, менее частые обновления местоположения могут быть полезны в радиусе 2 * R
  • За пределами радиуса 2 * R информация о местоположении может не потребоваться

Вы можете передавать информацию о местонахождении для объекта, периодически сканируя объекты в радиусе 2 * R (или несколько кратные таковым в зависимости от частоты обновления и максимальной скорости объекта) и подписывая объект на точный или неточный фид местоположения другого объекта.

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

Дэвид Н
источник