Представьте себе открытый мир с более чем 500 игроками, данные которых меняются со скоростью 20 обновлений / игрок / секунду. В прошлый раз, когда я работал в похожей MMORPG, он использовал SQL, так что, очевидно, он не мог все время запрашивать БД. Вместо этого он загружал все проигрыватели из БД в память как объекты C ++ и использовал их. То есть он масштабируется по вертикали. Можно ли вместо этого сделать этот сервер горизонтально масштабируемым? Существует ли база данных, предназначенная для поддержки такого количества обновлений одновременно?
mmo
data-structure
databases
scalability
MaiaVictor
источник
источник
Ответы:
Тестовый случай с участием 500 игроков, это 250 тыс. Потоков информации, летающих с частотой 20 Гц. Для этого внутренняя полоса пропускания, при условии, что каждое сообщение составляет 100 байт, составляет около 500 МБ / с. Звучит амбициозно. Особенно между процессами.
Если вы разделили игроков на группы по 100, это снизит до 20 МБ / с и так далее. Вот почему у ММО есть зоны, и в этих зонах мало пузырьков влияния и так далее вниз, пока пропускная способность не станет разумной.
Первоначальная проблема заключается в том, что если у вас есть 10 человек, которые делятся информацией в режиме реального времени, но вы хотите, чтобы 500 делилось информацией, это означает экспоненциальный рост количества каналов связи и как мы можем обойти это . Я боюсь, что нет волшебной пули, о которой я когда-либо слышал, которая могла бы волшебным образом заставить геометрическую прогрессию исчезнуть.
Не используйте базу данных для общения, вот для чего нужен обмен сообщениями. Используйте базу данных для обеспечения транзакций и хранения информации, которую игроки не потеряют. Большинство ММО, с которыми я знаком, обновляют базу данных динамической информацией об игроке каждые 1-10 минут или в удобных точках, таких как переходы зон или вход в «безопасные» зоны в дизайне.
Вы , возможно , придется перепроектировать в игре необходимо для каждого игрока, независимо от того , как далеко, чтобы в реальном времени обновления содержимого рюкзака каждого другого игрока.
Также измените шаблон обновления с 20 Гц на скорость, основанную на расстоянии, кому-то на расстоянии в 1 милю не нужно знать, что вы переместились на 1 фут точно с 230,6 секундами, затем с другой ногой на 231,4 секунды, они могут справиться с тем, что вы двигаетесь на 15 футов каждые 10 секунд. секунд.
источник
Использовать фильтрацию областей интересов. Если мир разбит на 3 сервера, а область на сервере 1 находится далеко от области сервера 3, у них нет никаких оснований делиться информацией об объектах вообще.
Аналогично, на одном сервере отправляйте только соответствующую информацию клиентам. Если игрок A находится на совершенно противоположном конце карты от игрока B, то нет никаких оснований отправлять обновления о B в A или наоборот.
Когда у вас есть несколько серверов в непрерывном мире, у вас будут сущности рядом с краем на сервере 2, которые близки к сущностям на сервере 1. Вы можете отправлять обновления с «авторитетного» сервера для сущности на другой сервер (при необходимости) и аналогичным образом пересылать любые сообщения уполномоченному серверу в зависимости от ситуации.
Да, в этом случае один сервер будет немного устаревшим для определенных лиц. Не пытайтесь решить это. Просто разберись с этим. Предположим, что сущности могут быть немного устаревшими. Делайте любую логику, которая нуждается в обновленной информации только на сервере, который авторитетно владеет объектами. Когда объект влияет на другого, отправьте сообщение и предположите, что может потребоваться несколько тактов игровой логики, прежде чем он будет обработан и ваш вид обновится.
Такая конструкция также значительно упрощает работу с одним сервером. Ни одна сущность не должна напрямую изменять другую, только отправлять сообщения, и предполагается, что локальные кеши прокси-серверов для каждого потока слегка устарели.
Например, если сущность A атакует сущность B, не проверяет жизнь B, а затем отправляет сообщение о смерти, если оно достигает 0. Просто отправьте «поврежденное» сообщение, пусть уполномоченный сервер для B обработает его, а затем обработает любой сообщение «объект умер», отправленное сервером B позже, если объект A заботится об этом.
То же самое относится к любому крупному, масштабируемому неигровому приложению. Центральная база данных - это не волшебная технология мгновенного обмена. Два сервера должны обмениваться сообщениями асинхронно в пакетном режиме, чтобы поддерживать высокую пропускную способность. Отсюда и популярность таких технологий, как AMPQ и тому подобное. Базы данных предназначены для хранения и поддерживают синхронизацию, что позволяет использовать их для связи, а не потому, что они сами предназначены для синхронизации или связи.
источник
Возможно, вам будет интересна эта статья о Gamasutra , где разработчики Eve Online обсуждают, как можно успешно запустить игру с 400 000 активных игроков ... в одной базе данных SQL.
источник
Не думайте, что база данных - это некая некая модель общего мира в реальном времени, которая постоянно хранит все обо всем - как вы заметили, это не может сработать.
Вместо этого относитесь к базе данных как к автоматически обновляемому файлу сохранения: вы обновляете базу данных только изредка, например, когда игроки входят или выходят из игры или переходят из одной зоны в другую, или когда происходит что-то важное, чего вы не хотите потерян в случае сбоя сервера.
Фактическое состояние мира в реальном времени должно храниться игровыми серверами в памяти, как в вашем первоначальном примере. Уловка горизонтального масштабирования заключается в том, что не каждый сервер должен знать все в любой момент . Например, если игрок A играет в зоне A на сервере A, серверу B, управляющему зоной B, обычно не нужно знать, что у игрока A в рюкзаке - и, если это так , по какой-то причине нужно (например, поскольку игрок B в зоне B накладывает на А какое-то заклинание удаленного шпионажа, он может просто запросить эту информацию у другого сервера .
Для этого требуется, чтобы вы четко распределяли обязанности между серверами, поэтому, когда сервер B хочет узнать о рюкзаке игрока A, он будет знать, какой сервер имеет на нем достоверную информацию. Вы также , вероятно , захотите включить какой - то механизм подписки обновления, так что , например , сервер B может просто сказать сервера А « у меня есть кто - то шпионит игрока А, держать меня в курсе обо всем , что они делают , пока я не скажу иначе. » Вы, вероятно , также хотите включить какую-то глобальную систему вещания для важных глобальных событий, о которых игрокам, возможно, потребуется знать, где бы они ни находились; Конечно, такие события также должны регистрироваться в базе данных, но их активная широковещательная рассылка на все серверы означает, что серверам не нужно будет опрашивать базу данных на предмет обновлений.
источник
Другие ответы хорошо показали, как использовать базу данных, а не использовать базу данных для связи. Еще один аспект, на который вы можете обратить внимание, - классифицировать ваши обновления в зависимости от того, как информация должна быть передана другим организациям. Вместо того, чтобы связывать области с серверами, вы можете распространять свои сообщения и использовать механизмы pubsub для обмена обновлениями между сущностями. Например, вы можете по-разному относиться к местоположению в зависимости от того, кто рядом с вами:
Вы можете передавать информацию о местонахождении для объекта, периодически сканируя объекты в радиусе 2 * R (или несколько кратные таковым в зависимости от частоты обновления и максимальной скорости объекта) и подписывая объект на точный или неточный фид местоположения другого объекта.
У вас могут быть разные стратегии для разных типов информации, группировать общие вещи в одни и те же очереди сообщений или иметь разные очереди для сообщений, которые нужно отправлять разным объектам (или просто отправлять их самому широкому набору объектов и отбрасывать сообщения, если они не полезны).
источник