Як зберігаються дані mmorpg?


22

Я хочу використовувати базу даних sql у своєму сервері.exe.

скажемо, 1000 користувачів в Інтернеті. І гравці будуть змінювати свої дані, коли вони грають. І сервер повинен зберегти ці оновлення.

Але як ?

я думаю, що існує два способи:

1) сервер буде економити в операційному режимі під час роботи, а десь або погодинно сервер запише дані (оновлення) в базу даних sql від оперативної пам'яті. Але якщо електроенергія піде або сервер якось відключиться, оновлення не збережуть. Звичайно, я не хочу втрачати оновлення.

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


11
Ви зробили якісь орієнтири? Що ви думаєте, що операції з базою даних будуть проблемою для вашої гри?
congusbongus

3
Якщо ваш ігровий стан насправді реляційний? Ви впевнені, що хочете базу даних SQL?
Зупиніть шкодити Моніці

6
Також прочитайте, як обробляти паролі за допомогою хешей. Або принаймні сповістити користувача про те, що їх пароль зберігається як звичайний текст, щоб вони не могли використовувати інший захищений пароль.
TomTsagk

24
Як зауваження, якщо ви хочете створити комерційний MMO, і ви задаєте подібні питання, ви, мабуть, повинні почати з чогось меншого. MMO - це надзвичайно важко зробити взагалі, не кажучи вже про те, щоб зробити їх правильно, і вони не такі великі з ділової точки зору. Якщо це лише особиста річ, і ви хочете грати багато гравців, почніть з 64 гравців, а потім працюйте вперед. Це буде набагато простіше, ніж спробувати спроектувати "ідеальну" архітектуру з нуля без досвіду. Дивіться це .
Фонд позову Моніки

1
Ви можете написати загальний API, який є агностиком для зберігання даних. Потім запишіть адаптер, який зберігає дані в оперативній пам'яті для затримки зберігання. Або ви можете записати адаптер, який кешує дані у тимчасовий файл, перш ніж переправити їх у SQL DB. Таким чином ви можете вмикати та вимикати кешування, щоб з’ясувати, що найкраще. Вам не потрібно писати надто мушмутний додатковий код, якщо ваша архітектура побудована правильно.
0xC0DEGURU

Відповіді:


37

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

Проблеми, які ви відмічаєте щодо відключення електроенергії, є дійсними, але менш вірогідними, ніж такі проблеми, як збої в процесі (надійність роботи в режимі бездротового зв'язку, як правило, одна з тих речей, за які ви б заплатили центром обробки даних). Але все ж. Ви пом'якшуєте ці проблеми за допомогою таких налаштувань інтервалу збереження (тому відмова коштує лише максимум декількох хвилин прогресу), розповсюдження черг збереження на декількох машинах, агресивно розбираючи обсяг даних, який потрібно зберегти, та впроваджуючи перезавантажуване збереження черги.

Взагалі кажучи, використання самого сервера SQL в якості основної пам'яті буде неприємно повільним (громіздким). Я не бачу достатньо деталей у вашій пропозиції, щоб можна було впевнено сказати, чи буде вона працювати лише для близько 1000 гравців - це, мабуть, буде добре. Але я не вірю, що ти можеш зробити це агресивно масштабованим.

Далі це не вирішує проблему. Відключення живлення під час процесу збереження все одно втрачає або пошкоджує дані, якщо ви не зробите роботу по впровадженню одного і того ж виду перезавантажуваної черги збереження (що навіть тоді, це лише сильно зменшує ймовірність катастрофічної втрати даних, це не заважає) .

Я б рекомендував вам піти з першим підходом.


10
Щодо "налаштування інтервалу збереження", то останній MMO, над яким я працював, мав інтервал збереження залежно від кількості активних гравців. Ми знали, що він може обробляти дані X гравців за секунду без помітного зменшення вузьких місць, тому нам просто довелося економити трохи менше X гравців за секунду на обертовій основі. Зазвичай це економить кожного гравця кожні дві хвилини або близько того у напружені дні, а може, і двічі на хвилину у повільний час.
Середнє значення

4
"Позачергова черга збереження" звучить як журнал, як це реалізовано багатьма файловими системами та двигунами баз даних?
grawity

6
Ці проблеми не є унікальними для НММ, або навіть відеоігор, на всіх . Практично кожен існуючий ORM забезпечує певний механізм кешування / пакетної обробки. Немає необхідності просувати власне рішення.
BlueRaja - Danny Pflughoeft

3
Якщо ви все-таки збираєтесь із збереженням на диску через певний проміжок часу, я рекомендую створити систему, де можна негайно зберегти речі, коли люди отримують рідкісні краплі / вмирання / тощо. Таким чином, якщо станеться збій на сервері чи щось подібне, люди, які здійснили щось велике, не будуть занадто засмучені.
Джон

5
@Jon, і тоді ти стикаєшся з проблемою того, що люди можуть дублювати об’єкти. В ідеалі ви зберігаєте весь стан гри періодично як одну транзакцію. Після того, як ви почнете зберігати поодиноко, ви закінчитесь ситуаціями, коли збій може спричинити непослідовні дані; гравці, які можуть викликати аварію на вимогу або навіть передбачити, коли трапиться збій, можуть використати це на свою користь.
Марк

15

1000 гравців можуть чи не можуть бути проблемою. Це залежить від того, як часто потрібно оновлювати базу даних. Однак є просте рішення: розмістити базу даних на власному сервері.


Я зазирнув до того, як працює система баз даних у грі, яку люди називатимуть MMO-Lite - яку я не розкриватиму, - але я можу сказати, що вона постійно має понад 1000 гравців, це реферат:

  • Вони використовують базу даних "No-SQL" на основі документа для інформації про приватні символи (інвентар, обладнання тощо).
  • Вони використовують більш традиційну реляційну базу даних для публічної інформації про персонажів, яка оновлюється рідко (ім'я, досягнення тощо) та статистику.

Використання бази даних на основі документа виявляється хорошою ідеєю для ефективності в цьому випадку. Це добре для доступу до даних, навіть якщо це погано для об'єднань та об'єднань ... але вони не будуть робити цього з даними, які є там.

З іншого боку, коли їм потрібно зробити щось на зразок змінити об'єкт на інший для кожного об'єкта, необхідність запускати фоновий скрипт, який набирає символів за символом та оновлює їх по черзі, це потребує помітного часу.


Дані символу існують як на клієнті, так і на сервері, і система призначена для синхронізації, виконуючи однакові операції з обох сторін.

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

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

Примітки :

  • Оновлення бази даних, хоча і асинхронізовані, проводиться відразу. Якщо з будь-якої причини ігровий сервер виходить з ладу, втрачається не багато.
  • Зниження продуктивності не є великою справою завдяки розміщенню баз даних на власних серверах.

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


Іноді щось йде не так, це має два можливі результати:

  • Якщо помилка трапиться відразу, сервер повідомить клієнту, який відновить операцію (гравець бачить, що операція не завершена).
  • Користувальницький інтерфейс каже, що у гравця є елемент, але сервер не погоджується. Якщо користувач намагається ним скористатися, він попросить сервер і вийти з ладу, зробивши підроблений об'єкт непридатним. Помилковий об’єкт відходить, коли інвентар перезавантажується, що використовується як можливість синхронізувати модель.

В будь-якому випадку клієнт знає про помилку, і записуватиме її разом із усім, що робив гравець. Реєстрація клієнтської сторони відбувається постійно. Потім при виході, якщо сталася помилка, клієнт відправляє журнали на сервер.


Ця гра не використовує традиційний щоденний або тижневий час виходу з ладу, який має більшість MMORPG. Таке планове обслуговування часто використовується для скидання лічильників, таймерів, запуску процедур баз даних. Вони також є можливістю міняти версії сервера для оновлення.


Дякую, але як щодо руху гравців, наприклад, якщо гравець рухається зі своєї поточної позиції: x:10,y:10,z:10До x:11,y:11,z:11, чи слід це негайно зберігати в базі даних? Що робити, якщо гравець продовжує працювати, це означає, що ми зберігаємо його поточну позицію кожні 1 секунди або менше, а якщо є тисячі гравців, це мільйони запитів до БД щосекунди. Це так працює?
dwix

2
Позиція гравця повинна зберігатися в базі даних дуже рідко. Ви хочете лише, щоб на спеціальних заходах, таких як відкриття меню, запуск багаття, відпочинок тощо. Залежно від гри, це навіть не буде збережено настільки детально. Деякі ігри змушують вас нерестуватись у найближчому місті тощо, так що це також збереже клопоти щодо збереження позиції. Але це відштовхується від думки.
Ніко

1
@dwix у випадку гри, про яку я говорю, позиція гравця навіть не зберігається. Якщо ви вийдете з системи та ввійдете в систему, або якщо сервер не працює, програвач буде повернутий у безпечне відоме положення (редагуйте: це приватний екземпляр, якщо ви хочете, але це однаково для всіх). Однак деякі ігри зберігають точну позицію гравця, навіть при випадковому відключенні. Для цього звичайний підхід зберігає цю інформацію рідше. Незважаючи на те, ви не робите те, що сервер чекає на базі даних.
Theraot

1
@dwix, коли говориш про положення аватара, ти не дуже переймаєшся історичними цінностями, чи не так? Ну, якщо база даних - це горлечко для пляшок, то вимкніть дані. Замість того, щоб зберігати кожен галочку на сервері, зберігайте рідше. Це означає, що база даних не матиме найновішого значення, але це не вплине на продуктивність настільки сильно. Тим часом сервер все ще зберігатиме значення оновлення в оперативній пам'яті, і саме з цим він працює. Додаток: Чесно, я б порадив не зберігати позиції, але деякі ігри роблять це.
Тераот


7

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

EVE Online - приклад MMO, де все зберігається в базі даних SQL. Я думаю, що він досяг свого максимуму близько 60 000 одночасних користувачів і мусив протягом багатьох років присвячувати дороге обладнання на сервери баз даних, щоб не відставати від навантаження. Однак EVE зберігає набагато більше даних на користувача, ніж більшість MMORPG і має набагато частіші та різноманітні транзакції. Властивості ACID бази даних дозволяють утримувати всю масивну та складну базу даних у постійному стані.

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

MMORPG, який зберігає дані гравця в пам'яті та періодично перевіряє їх, повинен сам реалізувати цю атомність. Одним із способів зробити це буде перевірка даних кожного гравця одночасно, гарантуючи, що новий контрольно-пропускний пункт буде повністю зафіксований на диску, перш ніж його вважати останньою контрольною точкою. Гра також повинна гарантувати, що дані гравця не можуть змінюватися під час перевірки. З великою кількістю активних гравців виклик стає робити все це, не викликаючи затримки достатньо довго, що гравці помітять.

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

Зауважте, що більшість MMORPG використовують бази даних SQL для інформації, пов’язаної з обліковим записом, навіть якщо вони не стосуються фактичних даних про ігри. Ще важливішим, ніж збереження ігрового стану в постійному стані, є збереження стану виставлення рахунків. Найгірший випадок пошкодження бази даних ігор - це те, що вам доведеться відновлювати базу даних із щоденної резервної копії. Найгіршим випадком пошкодження бази даних рахунків є те, що ви збанкрутуєте через усі збори.

Для вашого проекту, ймовірно, ви можете піти в будь-який бік. Наявність 1000 одночасних користувачів, ймовірно, не висуває межі того, що сервер SQL може обробляти на товарному ПК сьогодні, але багато що залежатиме від характеру транзакцій. Якщо ви знайомі з дизайном SQL і реляційними базами даних, це може допомогти вам. Ви хочете максимально мінімізувати транзакції, для чогось подібних поточних точок відтворення гравця ви можете лише періодично зберігати їх у базі даних, оскільки такі статистичні дані не обов'язково повинні бути послідовними. (У грі PvP вони можуть хоч ...) Не зберігайте в базі таких речей, як монстр HP, у більшості ігор зберігаються лише дані, пов’язані з гравцем.

З іншого боку, якщо ви не майстер SQL, ви можете зберегти всі дані в пам'яті набагато простіше, щоб надійно працювати. Бази даних SQL спрощують узгодженість та надійність, але не є автоматичними. Неправильно розроблена база даних може працювати погано і призводити до невідповідностей. Операції не будуть атомними, якщо ви їх не зробите. Якщо ви не використовуєте параметризовані висловлювання релігійно, ви відкриєтесь для атак ін'єкції SQL.


0

Різні ігри зберігають речі по-різному. Часто ігрові компанії створюють певний спосіб зробити це, і більшість своїх ігор використовують той самий спосіб. Звичайно, різні студії часто використовують різні способи. SQL, безумовно, використовується для ігор, наприклад CCP (EVE) має (або принаймні мав) мережу SQL-серверів, я не впевнений, як вони це роблять зараз. Інші, просто використовують багато файлів.

Може, почати зі створення агностичного "механізму брокера даних" для обробки різних ігрових транзакцій? Оскільки ви все одно просто тестуєте, створіть механізм, який дозволяє вам не надто піклуватися про сховище, з точки зору самої гри. Значення, зосередитись на тому, як із хост-програми ви збираєтеся це впоратися.

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

Зберігання даних саме по собі, швидше за все, не стане проблемою. Ефективна доставка даних до / в цей магазин, між хостом та всіма клієнтами, може бути складнішою. Чи надсилаю я весь набір даних про програвач чи розбиваю його на частини, яку деталізацію я вибираю для поділу і т. Д. Який ресурс інтенсивніший у якій ситуації тощо.

Одним із форматів для передачі даних може бути XML. Таким чином, ви можете бути легше динамічним, як це ви можете зібрати. Один символ проти кількох символів, або один елемент проти колекції предметів тощо. Потім ви можете "зберігати" XML як XML (у SQL) та / або змусити SQL поширювати його більш транзакційним способом від XML, як ви хочете, щоб дані фактично зберігалися.

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

З 1000 клієнтами ви можете почати і легко зберігати 10 Мб на клієнта і використовувати лише 10 ГБ ефективної оперативної пам’яті + додати деяку системну адміністративну ОЗУ для управління цими даними, скажімо, ще один ГБ або два. Ви можете зберегти це в оперативній пам'яті на хості вже в структурі даних, готової до використання. І завантажувати / зберігати динамічно, залежно від того, хто в мережі, на різних частотах, залежно від активності тощо.

Ви навіть можете зберігати інформацію кожного клієнта в окремому файлі тощо.


0

Утримуйте * онлайн * гравців в операційній пам’яті та підписуйте їх до бази даних (SQLite? MySQL?), Коли вони виходять. якщо ви турбуєтесь про затримку IO під час виходу, дайте кожному виходу свій власний потік, не робіть цього в основному / ігровому потоці (фактично я зберігаю спеціальний потік програвача для кожного онлайн-гравця, це зробило мережевий код набагато простішим ніж виконувати підхід до мережі асинхронізації)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.