Pull to refresh

Comments 169

Тот самый случай, когда хочется что-то спросить, но сознание выдает «продолжайте, хочу еще»!
В видео есть немного того самого «ещё» :) В том числе и интересная Q/A сессия.
Что-то вроде Active record используете или все запросы руками?
Что-то вроде Active record, через Hibernate. Запросы руками пишем крайне редко, в исключительных случаях для перфоманса.
А можно чуть подробнее про использование Hibernate? Был уверен, что на таком высоконагруженном проекте Hibernate будет тормозить. Вы используете StatelessSession или обычную HibernateSession? Если второе, то какое у нее время жизни? В обычных веб-проектах она создается одна на время Http-запроса
HibernateSession. Время жизни — одна транзакция.

Hibernate работает медленнее, чем JDBC, но т.к. latency одной датабазной бизнес операции находится в нужных нам пределах, мы на этом не заморачиваемся. Если что-то начинает тормозить, то это разве что из-за некорректно сгенерённого запроса. В этом случае мы запрос просто переписываем руками.
Hibernate будет тормозить.


С чего это вдруг? Хибернейт медленно работает только в случае плохого кода или плохой архитектуры.
Еще было бы интересно хотя бы вкратце услышать о том, как осуществляются связи между «маленькими базами». Структурно это копии одной базы, но с разными данными или же есть базы с разными структурами? Банально, если произошел обмен предметом между двумя игроками, наверняка была сделана запись об этом событии, содержащая ID обоих аватаров. Где хранится эта информация?
«Маленькие базы» делятся на типы, и их у нас около 12. Внутри одного типа структура одинаковая, и данные размазаны между базами. Связь между ними осуществляется посредством распределённых транзакций или не осуществляется вовсе, если это не нужно :)

Если произошел обмен предметом между двумя игроками, мы логируем это в специальную систему для гейм мастеров, но про неё я пока ничего скажу, это предмет отдельной и большой статьи.
А из какой игры первый кадр?
Каким образом обеспечиваете консистентное состояние при взаимодействии с двумя и более базами данных одновременно? Например, при продаже предмета нужно зачислить деньги одному игроку на шарде А и списать деньги с другого игрока на шарде Б. В целом, как обеспечиваете и обеспечиваете ли вообще атомарность распределенных изменений, затрагивающих несколько шардов? Спасибо.
А что будет если менеджер two-phase коммита умрет в момент совершения транзакции, которая prepared на обоих базах данных, но закоммичена только на одном из них?
«менеджер two-phase коммита» ведёт свой лог. После рестарта он поймёт что происходило и сделает правильный recovery.
выходит до рестарта менеджера 2PC данные в базах не консистентны?
До рестарта данные в одной базе уже правильные, а во второй они заблокированы. В общем да, в некотором смысле не консистенты. Но это не беда, мы сервера всё равно скорее всего остановим, если у нас всё упало :)
Как вы мониторите такие ситуации? Правильно ли я понимаю, что когда такое случается (кстати, случалось на практике?) вы показываете пользователям «сожалеем, у нас технические проблемы»?
Это уже дело админов. У них есть средства мониторинга всякие.
А кто выполняет роль этого менеджера? Где про его поведение можно почитать?
BTM — это и есть XA менеджер, он и выполняет. Ссылка есть в ответе на мой первый вопрос.
Интересно… а вы мерили какие лаги привносят эти XA-транзакции? И как можно обойтись без них, хотя бы частично?

И почему был выбран BTM? На Atomikos не смотрели?
— Меряли. Получалось что распределённая транзакция в несколько (3-5-10 в зависимости от кол-ва баз) раз медленнее чем обычная.

— Без них можно обойтись дизайном, так чтобы все взаимодействия были максимально локальными. Или иeventual consistency.

— Атомикос пробовал, не взлетел. Пришлось его выпилить и вместо него взять BTM. Атомикос не работал из коробки, пришлось ручками подписывать что-то в коде, а код там ужасен. Он даже не отформатирован. Кроме того там полно багла, и ему надо явно говорить «а вот эта транзакция будет распределённой и в ней будет 2 вот такие вот базы». BTM умеет сам это понимать. В целом Атомикос удалось заинтегрить за 2 недели, а потом я выпилил его нафиг и заменил на BTM за 2 дня.
Спасибо, статья интересная.
А можете на ушко шепнуть когда ждать Skyforge и стоит ли его ждать?
Ждать стоит, игра крутая. Когда — сказать не могу. NDA.
А игра будет для народа, или же только для состоятельных людей, как и Аллоды Онлайн?
Вроде на видеозаписи говорится о free-to-play
free-to-play == только для состоятельных людей
Для кого-то игра по подписке == игра для состоятельных людей, для кого-то платные игры на AppStore == игра для состоятельных людей, а для вас FREE-to-play?
F2P = вы можете бесплатно играть в игру, вкладывая ровно столько усилий и времени сколько вы захотите, вы можете сэкономить время, оплатив в том числе развитие игры и «бесплатную» игру других игроков. Покажите мне игру в которой вы сразу получаете самый последний уровень и все преимущества и объясните мне зачем тогда в нее играть?
F2P-игра от mail.ru Бумз.
Можно получить все преимущества, если имеешь резиновый кошелек.
Друг играет, говорит, что даже при вложениях 1000-3000 рублей в месяц, комфортной игры ты не получишь.
Зачем тогда он ест этот кактус?
Я ему тоже самое говорю.
Ответ: «Много уже вложил».
В некоторых F2P играх люди вкладывали $100K и всегда находились те, кто вкладывал еще больше. Если для друга комфортная игра = нагибать всех вокруг, то все вокруг будут думать иначе. В ММО играх нет «я с одной стороны» как в Single Player и «злые разработчики с другой», а есть «я против всех игроков».
Это довольно холиварная тема. В конце концов каждый сам решает — подходит ему эта схема или нет. Для меня игра — возможность расслабиться, окунуться в новый мир. Это как кино или книга.

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

Тут кто-то спросил: «Зачем тогда он ест этот кактус?». Вот именно. Я не ем. Мне проще заплатить один раз и играть.
Это не современные f2p, это чмошные f2p. Посмотрите на LoL, Path of Exile. Они f2p, но там можно отлично играть, вообще ничего не вкладывая.
У нас же в основном выпускают такое ф2п, что это бросает тень на всю модель монетизации.
Однако игры, о которых вы говорите, не ММОРПГ. Тут нельзя сравнивать. Жанр то другой.
Пару лет назад, менеджеры ололодов писали, что их ф2п игра рассчитана на игроков, которые могут вкладывать в нее ~500$ в месяц а к мнениям остальных они прислушиваться не собираются.
p2w (pay-to-win) для состоятельных людей. Посмотрите игры от Hi-Rez, или firefall тот же. У них очень грамотная модель f2p.
Они ж пустили P2P сервер на Аллодах. Думаю, это можно рассматривать либо как сегментацию, либо как пилот этой модели распространения. Исходя из того, что на закате многих проектов наоборот происходит миграция с модели p2p на f2p, заключаю, что скорее второе — т.е. пилот. Соответственно про результатам пилота, скорее всего, и будет принято решение. И повлиять на это решение можно самостоятельно, оформив подписку ))

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

Увидел много знакомых проблем, с которыми приходилась встречаться в геймдеве. И так же использовался PostgreSQL, с разницой в том, что нереляционные данные хранились в NoSQL.

Вы написали, что с удовольствием ответите на вопросы по БД в онлайн-играх. У меня есть несколько :)

1) Поделитесь, как вы проводите обновления на вашей архитектуре?

Допустим, при планируемой нагрузке в 100к онлайн и 7к транзакций в секунду, вы хотите выкатить обновление затрагивающее изменение структуры и индексов в нескольких таблицах в БД.

Интересно также, какое планируемое время рассчитываете тратить на такое обновление и будет ли оно производиться в один заход с приостановлением сервера, либо без, выдавая обновления сначала 10к пользователей, потом еще 10к и т.д. (как, если не ошибаюсь, происходит в Facebook).

2) Как вы храните логи?

Понимаю, что есть разные виды логов: действия, платежи, логины и т.д. Храните ли вы что-то в БД?
В разных проектах я видел разную архитектуру (а архитетура логирования, на мой взгляд, должна быть продумана не менее тщательно). Хотелось бы узнать о вашем опыте, граблях и методах их обхода.
Прошу прощения, третий вопрос пропал :(

3) Если это не конфиденциальная информация, интересно узнать, какое решение вы используете для синхронизации изменений в БД (как изменения данных, н-р в статических таблицах [«quests», «races», «configuration»], так и изменения структуры)?

Это какой-то программный продукт или собственная разработка/скрипт?
3. Если я правильно понял вопрос, то ответ такой — это просто набор sql скриптов, которые конвертируют базу при старте сервера.
1. У нас всё просто. Обновление на ходу мы не можем делать по 101 причине, поэтому устраивается «профилактика» в ходе которой все сервера гасятся и на них накатывается обновлённый код, ресурсы и т.п. При старте сервер автоматически конвертирует базу, добавляет туда индексы, переформатирует таблички и т.п. Скрипты конвертации зашиты в сервер и пишутся руками.

2. Логи бывают двух видов.
Просто логи сервера мы храним в файликах, но пытаемся прикрутить фейсбучный Scribe.
Логи покупок и прочих игровых действий мы храним в специальной большой базе/системе для гейм мастеров. Но про неё много очень писать надо, потом, может быть статья будет. Stay tuned :) Основная её идея в том, что она заточена под террабайты данных. Её делают специальные люди, и да, она совсем не простая :)
Логи покупок и прочих игровых действий мы храним в специальной большой базе/системе для гейм мастеров. Но про неё много очень писать надо, потом, может быть статья будет.

Очень хочется такую статью.
Очень интересная статья, спасибо! Интересует вопрос, который мучал меня при покупке SSD: насколько времени работы хватит одного диска? Как известно, у SSD главный недостаток — это ограничение количества циклов перезаписи. А учитывая, что у вас на SSD размещены файлы, «в которые идёт основная нагрузка на запись», он может прожить очень недолго.
Я тоже так думал, до тех пор пока Пётр Зайцев, на конференции, наглядно не посчитал, что при записи 100МБ/сек одного SSD хватит на 3 года. У нас трафик поменьше, так что волноваться не стоит. Диск умрёт раньше из-за каких-нибудь других причин :)
Недавно закончилось 3 месячное издевательство над Samsung 840 на базе TLC.
Один из дисков все таки умер, при расчетной нагрузке на запись 30GB в день он бы прожил около 20 лет.
При этом нужно понимать, что это TLC, а не MLC или SLC. И это Desktop, а не Enterprise (у них ресурс раза в 2 больше).
us.hardware.info/reviews/4178/10/hardwareinfo-tests-lifespan-of-samsung-ssd-840-250gb-tlc-ssd-updated-with-final-conclusion-final-update-20-6-2013
Спасибо за ссылку! Да, прогноз довольно оптимистичный :) хотя такая экстраполяция мне кажется довольно сомнительной. 20 лет все же ооочень большой срок даже для обычных HDD.
Распространение SSD началось всего 5 лет назад, поэтому прогноз даже на 10 лет вперед довольно сомнителен.
На самом деле в статье указаны еще более оптимистичные данные: время жизни указано при WAF 3 (write amplification factor), как если бы данные записывались в 3 ячейках вместо одной.
Если уменьшить расчетный срок жизни до 3 лет, то оптимист в день может записывать порядка 700GB.
Основная проблема вовсе не в этом, а в том, что SSD смертны внезапно.
Именно внезапно.
Т.е. вот работал себе диск, 100% здоровья все дела и бац нет у тебя диска, контроллеру крышка.
Происходит это случайным образом. При перезагрузке например.
У меня вот 2 SSD так умерло. Vertex и Crucial. Да и вообще судя по отзывам 99% дисков именно так и гибнут.
Да, их по гарантии поменяли без звука. Но вот эта вот внезапность больше всего убивает.
А ресурса записи у SSD просто завались.
Ну умер диск и умер. Эка невидаль. Бывает. Для этого и делается резервная реплика и бэкапы.
Да решение проблемы-то понятно. Эти решения были придуманы еще за долго до SSD.
Вопрос в том, что многие думают, что основная проблема это ограничение циклов записи. А это не совсем верно.
Судя по исследованиям Google SMART может предупредить вас о возможных проблемах, но в большинстве случаев этого не происходит. Насколько часто вы проверяете SMART?
При этом если потеря нескольких файлов допустима, то потеря куска БД равноценна потере всего диска — быстрее и надежнее восстановить из бекапа.
Насколько я понимаю, S.M.A.R.T. поможет предсказать падение HDD, не SSD.
Для SSD он лишь оценивает число циклов перезаписи и в принципе не может помочь при сломе контроллера, что является основной проблемой отказа SSD.
А я про HDD и говорю. HDD может упасть также внезапно, но чаще всего SMART предупредит когда fail уже произошел и потеряна часть данных (остальные ошибки он исправляет прозрачно для пользователя). Без установки дополнительного ПО вы (скорее всего) не узнаете о деградации диска.
Так здесь-то база на SSD.
А с ним проверять SMART бесполезно, все равно рванет неожиданно.
Сколько я видел SSD в деле — не доживают они до заявленных циклов перезаписи. Мрут. То одно в них сдохнет, то другое… Какова кстати у средняя живучесть SSD выходит при активном использовании? У меня такие подозрения что не выше года-двух.
Чёрт его знает, сколько они в среднем живут. Статистики я не видел. По личным печатлениям — у нас в офисе ломаются и те и те. Вообще SSD очень молодая технология и каждый следующий диск надёжнее чем предыдущий. Именно поэтому мы откладываем покупку дисков до самого последнего момента :)
А мы о каких SSD сейчас говорим?
— Есть на контроллерах SandForce, Marvel, Samsung, Toshiba, Intel, Indilinx, JMicron.
— Есть с памятью от Intel, Micron, Samsung, SK hynix, Toshiba
— Размер ячеек памяти бывает от 40 nm до 16 nm
— Тип ячеек бывает TLC, MLC и SLC (ресурс записи в 100 раз больше)
— Диски могут быть Desktop, Enterprise (в том числе SAS и PCIe)
— Поведение диска может значительно зависеть от качества прошивки
— В некоторых дисках может быть подобие внутреннего RAID массива
— В некоторых даже кеширование на DRAM.
Да кто-то ставит более дешевые компоненты чтобы снизить стоимость, но говорит ли это о том что все SSD диски «одинаково полезны»?
Как осуществляется взаимодействие игроков? Жахнул я фаерболом по площади, что дальше? Как сервер определяет, кто из игроков попал под воздействие? А теперь представим, что кто-то жахнул по той же площади. Как происходит синхронизация состояний в оперативной памяти разных процессов, если вы их не пишите в реалтайме в БД?

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

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

Более подробно я пока не расскажу, это потянет на полноценную статью :) Возможно она даже будет через некоторое время.
Тогда у меня вопрос, как один сервер потянет обработку 100 тысяч игроков :) В той же EVE отдельные звездные системы разнесены по разным серверам.
Никак. Игроки размазаны по картам. Карты находятся на разных машинах. Одна машина должна тянуть ровно столько людей, сколько будет на одной карте. И этим числом мы управляем :)
Так что таких батлов как еве у нас быть не может.
А как быть с ДДосами?
Все игроки пришли в столицу, сервер с этой локацией лег.
Что делать? Ставить ограничение и мрачных секьюрити на вход в город?
Оххохох.
Ответ есть, но я не знаю попадает ли он под NDA или нет, так что промолчу. Сорри :)
Ну ёлки-палки, самое интересное же :(
А хотя бы указать, ляжет или нет, возможно? :)
«Билетов в этот город нет», «плохая погода мешает телепорту» ну и тд
есть подозрения, что вам не покажут вообще всех игроков, а город распараллелят на несколько серверов, с более или менее хитрыми алгоритмами распределения тех, кто будет в одной локации с вами.

что-то не представляю какие еще решения могут быть настолько шокирующими, что бы попадать под NDA =)
+ как правило в городах запрещено пвп, и взаимодействие между игроками сведено к минимуму.
Растяжение времени (Time Dilation), как в EVE Online? ;)
Я правильно понял, что из этого следует что за определенную локацию отвечает определенный сервер гейм механики, который знает об аватарах которые там находятся и разруливает все их взаимодействия. Если так, то как определяется какой сервер за какую область отвечает? Грубо говоря, это задется в конфигах, или это какой то умный механизм.
Именно так. На каком сервере какая карта будет, решает специальный умный балансировщик.
А есть ли пограничные ситуации. Например, две карты А и Б граничат между собой, но находятся под управлением разных серверов, игрок из А жахнул фаерболом по игроку из Б :). Возможна ли такая ситуация и как она разрешается?
На Аллодах был специальный механизм для этого, но в Skyforge мы от этого отказались. Много багов, мало толку. Разные карты у нас не граничат, хождение между ними только через телепорты.
Аватар за последнее время это с одной стороны высокий синий человечек из инопланетных джунглей с глуповатой улыбкой, а с другой лысый мальчик-монах со стрелкой на лбу.
Т.к. Вы нашли ему и иное применение, как бы не запутаться теперь, я правильно понял что речь идет о сущности в hybernate?
Вообще было интересно почитать, хотелось бы еще немножко статистики увидеть в цифрах.
Вобщета аватары были аватарами и до фильма. В фильме же заимствовали этот прижившийся в айти термин ибо туда он весьма подходит по смыслу.
Вообще, слово «аватар(а)» пережило уже не одну тысячу лет «последнего времени» и по прежнему сохраняет свой смысл воплощения в нижестоящей виртуальной реальности ;-)
А фильм — даже не все смотрели
На SSD достаточно положить файлы WAL PostgreSQL, в которые идёт основная нагрузка на запись, а остальные данные можно разместить на более медленных дисках.

Разве не наоборот надо?
Для WAL файла достаточно HDD — скорость последовательной записи постоянна и достаточна.
А файлы с данными — на SSD, чтобы рандомное чтение/запись было быстрым?
Согласен, но при тюнинге fsync-а WAL лично я постоянно упирался в latency а не throughput. На SSD latency существенно меньше.
Наверно, при слишком активной записи это правило становится не таким актуальным, поскольку даже при линейной записи метаинформацию ФС должна обновлять, а это как ни крути, но задержки. Диски же на 15к оборотов заставляют задуматься о том, что даже быстро вылетающие SSD — выгоднее.
Но буквально три недели назад мы наконец-то всё поняли и теперь храним данные в реляционной схеме с JSON-вставками.

А почему не постгресовый хэшстор?
Спасибо, я о нём тупо не знал до этого момента. :)

Посмотрел, вроде примерно то что надо. Впринципе можно было бы и его заиспользовать. Разница с JSON-ом на самом деле минимальна. JSON начиная с версии 9.3 такой же встроеный тип как и hstore, с поддержкой на уровне базы.

Но с кастомными типами есть один неприятный момент. Их сложно сращивать одновременно с hibernate-ом и постгресным jdbc драйвером. Когда я это пробовал, мне пришлось немного подхачить драйвер, чтобы в коде у меня всё это выглядело красиво, что уже не есть гуд.
UFO just landed and posted this here
Не обязательно весь объект наследовать от UserType. Можно сделать филд и пометить его аннотацией Type со ссылкой на соответствующий тип.

Примерно так
class DataSet {
 
 @Column(...) 
  int x;

 @Column(...)
 @Type(value="pkg.to.type.JsonType")
  Descriptor z;
}


Если мы один филд хотим разложить в 2 поля: json + поле для индексирования, можно использовать композитный тип.

class DataSet {
 
 @Column(...) 
  int x;

 @Column(...)
 @Type(value="pkg.to.type.CompositeType")
  @AttributeOverrides (
      @AttributeOverride( name="field_1", column=@Column(name="f1")
     @AttributeOverride( name="field_2", column=@Column(name="f2")
    ) 
  Descriptor z;
}



p.s. код писал без IDE, наверняка не скомпилится.
На самом деле, у hstore перед JSON почти нет преимуществ на 9.3. Индексы по JSON можно строить фактически любые, в JSON поддерживаются не только строки, но и числа и массивы и вложенность (в hstore и ключ и значение — строки).
У HStore есть одно, на самом деле огромное, преимущество — скорость. JSON в PostgreSQL хранится внутри как строковое представление, а HStore — в бинарном формате. При чтении/поиске HStore обгоняет JSON на порядок минимум. Недостатки тоже есть — нет вложенности (массивы PostgreSQL пакуются в HStore вполне нормально), но Олег Бартунов писал что в будущем 9.4 уже есть подвижки в эту сторону.
Кстати немного про скорость. Меня могут закидать помидорами, но я не считаю что скорость это так уж важно. Важен throughput и latency не более чем ХХХ. Если для игры/для игрока скорость (latency) хорошие, то я не пытаюсь сделать ещё лучше. Я пытаюсь улучшить throughput и сделать так, чтобы эта latency выполнялась для бОльшего количества игроков.

Ну например hibernate медленнее, чем прямой jdbc. Но его использование позволяет экономить время и потратить его на более лучшее масштабирование. В некотором смысле тоже самое верно и для JSON.
Вот хранили бы они JSON в чем-то вроде Msgpack например — уже получили бы прирост в скорости и размере.
С другой стороны, если накладывать на JSON поле какой-то функциональный индекс, то разница будет незначительная.
Недавно заменили MsgPack на Json, сериализует/десериализует в 2раза быстрее при 4х кратном проигрыше в размере, но размер в том месте был не важен.
Пруфлинк?
(Ну, точнее, поясните что за библиотека для JSON и MsgPack и какой язык программирования. И желательно какого типа в основном были данные — ASCII/юникод/числа.)
Без этого звучит как «заменили Ferrari на трактор и поле вспахали в 2 раза быстрее».
Вы написали, что постгрес оставил вам только проблему автовакуума, но не написали, как вы ее решаете.
Фулл вакуум каждый день во время профилактики? А если не успеет?
Автовакуумим по-чуть-чуть постоянно в бэкграунде. До вакуум фулл дело надеюсь не дойдёт :)
Ну мой опыт (9.2, но все же) подсказывает, что автовакуум почти не помогает, а без фуллвакуума постепенно накапливается сильная деградация производительности.
Т.к. мы ещё не в продакшне, то я теоретизирую. На тестах у нас вроде всё ок.

Т.к. у нас не одна большая база, а много маленьких, то, если всё будет плохо, мы сможем делать вакуум фулл по очереди… по 5 баз за профилактику :)
На тестах у нас вроде всё ок.

Когда мало данных, всегда все ок.

У нас в табличку размером 160 ГБ+индексы в день пишется пару сотен метров. Через несколько дней такой записи производительность селектов падает от нескольких сотен миллисекунд до нескольких минут. Как мы не бились, иначе чем Analyze по ночам, когда нагрузка уходит ничем помочь не смогли.

Так что готовтесь =).
Если место свободное есть (х2 от размера базы) то pg_repack должен помочь. Работает, естественно, в разы быстрее чем vacuum analyze :)
Спасибо, если припрёт, будем пробовать repack :)
На тестах у нас много данных, около 100 ГБ. И за ночной тест перезаписывается едва ли не половина данных. Пока всё ок, но, если что, мы готовы.
А много маленьких, это сколько?

И разве не имеет смысл делать много таблиц, а не баз, vacuum же можно организовать per-table

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

У нас и так в каждой базе много таблиц. Неудобно дробить каждую табличку ещё на несколько, а потом что-то думать как сделать между ними всеми foreign-key-и.

Я думаю, при наших объёмах, автоакуум будет успевать. Если нет, то «маленькая база» всё равно ведь будет гигабайта 2-3-4. Сделать полный вакуум всей базе это полчаса максимум. Так что всё будет хорошо :)
И как Вы решили проблему? У нас такая же фигня…
Переходом на mysql :)
Еще и скорость выросла.
Холивара не хочу, но постгресса после этого в моих проектах больше не будет.
Скажите пожалуйста, а как вы пытались бороться с потерей производительности на postgres до того, как перешли на mysql?
А какими средствами организована репликация между серверами БД?
Сервер БД выполняет необходимые проверки (достаточно ли в сумке места, не нужно ли «застекать» эту вещь и так далее). После этого он сохраняет обновлённое состояние сумки аватара в базу.

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

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

Как вам такая идея?
Отличная идея. Так в целом оно и работает :)

Вот только повторные проверки на сервере исполнения транзакций проводить всё равно надо. Представьте что вам подряд придёт две операции «поднять предмет», при том что у вас в сумке только 1 свободный слот. Гейм механика их пропустит, потому что на момент проверки второй операции она ещё не получила update от базы.
То есть у вас база главная?

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

Всё зависит от того кому вы больше доверяете — тем кто ответственнен за БД или за сервер механики :)
Кто персистентней тот и главней :)
База у нас главная, конечно же. И схема, которую я показал, немного упрощена. Часть запросов на аватара идёт не с механики, где он бегает. Да и вообще у нас иногда бывают операции по аватарам, которые не загружены.
Эти запросы не нужны когда игрок находится в рилтаймовой ситуации. Можно создать места на карте, при нахождении в которых приходят все эти внешние события. Игрок в бою — лочим полностью на гейм-сервер, игрок не в бою — снимаем лок.

Операции по незагруженым аватарам можно проводить через отдельный сервер механики.

Это всё из разряда «дёшево и сердито», конечно при ваших ресурсах это упрощение не нужно.
ни одна в мире NoSQL-база не может консистентно и транзакционно переложить предмет от одного аватара другому.

Не совсем правда, FoundationDB это умеет. И другие интересности у неё есть, например так серьёзно Fault Tolerance никто наверное не тестировал: раз blog.foundationdb.com/post/50924738464/foundationdb-fault-tolerance-demo-video
и два blog.foundationdb.com/post/53286213668/quicksand-continuous-real-world-fault-tolerance
Мне подобный вопрос уже задавали в личке, так что отвечу и тут.

Мы не рассматриваем платные и проприетарные базы. Цена для нас имеет значение. А то можно было бы и oracle прикупить, он тоже умеет в NOSQL режиме работать, вот только стоить он будет больше, чем наша серверная ферма :)
Графо-ориентированные базы (а они тоже попадают под течение NoSQL) таки держат классические ACID транзакции, например Neo4j. Но род задач, под которые они подходят весьма уникален :)
Правильно ли я понял:
1) Нагрузка на серверы игровой логики снижена за счет ограничения игровой механики? (Например, на одной локации одновременно может присутствовать лишь ХХХ игроков).
2) Один сервер игровой логики обслуживает одну локацию? На какое количество игроков расчитан этот сервер? Обмениваются ли эти сервера друг с другом информацией? Какой именно? Или обмен происходит через базу?
3) Вы упоминали о распределенных транзакциях. Что будет с производительностю если собралось 20 аватаров из разных шардов и они например коллективно что-то сделали? Распределенная транзакция на 20 шардов?
1. немного хитрее, но, как я уже говорил, тут я лучше промолчу чтоб случайно не нарушить NDA.

2.
>> Один сервер игровой логики обслуживает одну локацию?
несколько.

>>На какое количество игроков расчитан этот сервер?
NDA

>>Обмениваются ли эти сервера друг с другом информацией? Какой именно? Или обмен происходит через базу?
Инфрмацией они не обмениваются. Между собой они взаимодействуют косвено, через общие сервисы.

3. Да, это проблема. Для подобных случаев мы не делаем распределённую транзакцию на 20 серверов, это слишком. Мы делаем кастомный алгоритм с eventual consistency. К счастью таких случаев мало.
Кстати, не посоветуете ли книги или статьи на схожую тематику? Что вам помогает в работе?
Хотя бы здесь не удалят коммент о том, как же достали тормоза в ваших играх.
UFO just landed and posted this here
UFO just landed and posted this here
Спасибо, очень интересно. В свое время тоже занимался БД для игр (был такой проект — «Хоп-гоу»). Разделение на сервисную архитектуру для БД с частичным кешированием и сохранением только того, что нужно — знакомые подходы. Надо сказать, что перекрестная архитектура с резервным копированием — обычная практика. Мы так с Ораклом поступаем.
Перекрёстный бэкап я подсмотрел в докладе Evernote на какой-то конференции. Очень мне понравилась идея :)
За статью спасибо! И все клева, но один момент несколько обескуражил:
Но буквально три недели назад мы наконец-то всё поняли и теперь храним данные в реляционной схеме с JSON-вставками.
Ну вы хоть иногда делайте обзор сторонних решений. в том же xPDO это во всю используется Бог знает сколько. phptype=«json» и все.

$o->set($var, (array)$data); $o->save(); // записалась в базу JSON-строка.
$data = $o->get($var); // Получили данные в массиве.

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

Вопрос не праздный, разработчики всегда хотят все впихнуть в одну структуру (и я их понимаю), а архитектор БД — нормализовать (и это я, поэтому понимаю тем более). Как находите компромисс?
У нас на проекте я отвечаю за базы головой. Поэтому последнее слово за мной :) Это правда не исключает дискуссий и меня можно переубедить, что многим удавалось. :) В целом, мы по умолчанию пытаемся разложить всё в таблички. Если не получается или видим, что это будет плохо — думаем. Критериев формальных конечно же нет. Формализм зло.

Ну значит вы работаете в правильной компании.
Спасибо, но у нас с вами сервера локаций сильно разные :)
Нативная поддержка JSON (а не просто возможность сохранить JSON строку) появилась в PostgreSQL 9.2, а расширенная поддержка (ради чего стоит на него переходить) запланирована в PostgreSQL 9.3, который выйдет только в 3 квартале 2013.
«один момент несколько обескуражил:» Вы всегда используете beta-функционал в production?
1. При чем тут я? Приведенный пример был на PHP, если вы не заметили. И в базу пишется не какой-то особый объект, а простая JSON-строка, которая по сути своей никак не отличается от любой другой строки (если мы говорим о типах данных). Ни о какой нативной поддержке постгресом чего-то я и не говорил.
2. Если говорить про бета-функционал на продакшене, то да, бывает и использую. Если проект не очень важный, то почему бы и не погонять последние технологии на боевом проекте?
На тему SSD — может, имеет смысл заменить/дополнить SSD накопители дисками на основе RAM памяти (что-то типа этого)?
Во первых — а зачем? SSD достаточно быстр для нас.

Во вторых — Что-то как-то стрёмно :)

Итак, время жизни данных в i-RAM (при полностью заряженном аккумуляторе) для одного установленного модуля памяти исчисляется 24-32 часами, для двух модулей — 18-29 часов, а для 4 модулей — 12,6-24 часа в зависимости от типа модуля. То есть, более или менее уверенным в сохранности данных в i-RAM можно быть только в течение примерно 10-12 часов, если абстрагироваться от типа используемых модулей.
1. Ну раз хватает, так хватает :)
2. В случае ЧП за 10-12 часов базу с такого диска можно хоть на дискетки настрогать, а уж тем более не проблема перенести на обычный HDD или SSD.

Просто я подумал, что если производительности SSD вдруг будет не хватать, то i-RAM можно использовать в качестве «третьего слоя» над SSD.
10 часов это очень мало. Можно не успеть, если учесть что ночь, админы спят, сервера стоят в датацентре, и надо туда доехать, надо вспомнить какой где сервер, вспомнить что данные надо куда-то там перелить, найти пустой диск, вставить его в новую тачку, перекопировать всё и т.д.
А в каких ситуациях такая проблема может возникнуть? Ведь чтобы данные потерять, это ведь нужно, чтобы сервер неожиданно отключился и простоял выключенным 10 часов. Если отключится электропитание, то процесс переливания данных с i-RAM на SSD может пройти автоматически, пока работает бесперебойник, и тогда все будет нормально. Или Вы подразумеваете что-то типа выхода из строя блока питания?

P.S. У меня возникла неожиданная идея — ведь если у нас питания нет, то серверу об этом сообщит бесперебойник, и мы можем записать данные на безопасный носитель. А если есть, то мы в любом случае можем еще долго питать i-RAM от внешнего блока питания.
Обычный юзкейс — в час ночи сгорает материнка или тот же БП.

БП и прочие подпорки это всё сложно и ненадёжно. Всегда найдётся тот, кто забудет что-то подключить/закупить и поднастроить. Я бы не рисковал без крайней нужды.
Недавно писали о появлении в ближайшем будущем дисков совмещающих быструю DDR и медленную Flash память в одном чипе. При запуске данные читаются с флеш в память и периодически скидываются обратно, плюс внутри диска есть небольшой аккумулятор который позволяет сохранить всю информацию в случае факапа автоматически.
А в нынешних HDD кэш как сделан? Я думал, он как-то так и работает, как Вы описали. Или в тех дисках будет большая DDR память?
Поправка, это будут не совсем «диски» (они итак уже в SATA3 упираются)
Это не кэш, объем DDR равен объему Flash, информация сохраняется полностью без потерь
Сейчас есть похожие решения подключаемые по SDRAM, DDR2, DDR3 от Viking Technology, AgigATech и Netlist
Micron планирует выпустить в 2014 году Hybrid DRAM на DDR4
www.eetimes.com/document.asp?doc_id=1263046
Это отдельные чипы (DRAM+NAND), два контроллера(HDIMM+Flash) и ионистор (supercapacitor, ultracapacitor)
«В одном чипе» я похоже поторопился, NAND может стать одним из слоем в Hybrid Memory Cube (HMC) в 2015
По какой шине будет подключаться пока не понятно, при том что заявлена скорость 160 GBps (DDR4 «всего» 20 GBps)
Вот такая штука есть — habrahabr.ru/company/croc/blog/181494/
До миллиона IOPS держит.
Стоит правда, дорого. Явно не для использования в Skyforge (судя по высказываниям Randll). Больше для вертикального масштабирования подходит…
Всё же по Вашей ссылке речь про ms, а не μs
Тема с SSD напомнила давнюю историю с Eve Online, которые тоже полагаются вовсю на реляционный SQL Server, и перенесли его на RAMSAN-овский SSD от Texas Memory Systems. Это промышленный SLC SSD в стоечном исполнении и с контроллером на FPGA. Было это, кажется, в 2007-м. Так что для геймдева подход похоже работает неплохо.

Андрей, а в сторону In-Memory Data Grids для бекенда не смотрели? Мне кажется, для геймдева это может быть интересный вариант, чтобы преодолеть вертикальное ограничение — максимальное количество юзеров на одну тачку, из-за того что вы вынуждены юзать только локальные взаимодействия на одной карте, комнате или что там у вас является аналогом партиции.
Про In-Memory Data Grids. Мы не пробовали, для нас это оверкил пожалуй. Для надёжности нужно много серваков и в разных датацентрах. При большом желании мы сами бы смогли это сконфигурить, но игру потом всё равно придётся отдать зарубежным партнёрам, и они будут её разворачивать сами и на своём железе. Любая сложная схема будет уязвима для человеческого фактора. Самое ближайшее, на что я поглядывал, это MemSQL, но… хочется обойтись бесплатным софтом.

Впринципе, если PostgreSQL нам не хватит, я бы начал смотреть в сторону Тарантула. Во первых он наш, а во вторых его однотредовая архитектура нам ближе :)

Про партиции — базы и гейм механики это разные серваки и скалируются по разному. Как бы мы не масштабировали базу, механикам это не поможет. В целом, у нас нет потребности держать на одной карте больше народу, чем мы умеем сейчас. Нам просто не надо решать ту проблему, о которой вы говорите :)
Ок, спасибо за подробный ответ )
IMDG опенсорсные тоже есть — Hazelcast и Infinispan, например. И наконфигурять можно так, что кластер будет автодискавериться автоматически. Но если задачи горизонтально скейлить одну карту нет, то оно дейсвительно не надо.
Скажите, пожалуйста, можно коротко, в чем принципиальная разница между Virtual shards (который насколько я понял используется в skyforge) и шардингом (который используется в аллодах).
Кто раздает значения для Primary Key:
— postgres на основе сиквенца? если он, то с любой ноды идет выделение следующего значения секвенца?
— свой самописный сервис генерирует типа UUID на основе макадреса, времени и пр.
При создании базы сиквенсы сдвигаются так, чтобы генерить идентификаторы в нужном диапазоне.
Под диапазоном имеется ввиду min-max?
Или смещение относительно количества нод, содержащих одну и туже сущность, ну например:
— есть 2 ноды. значит один и тот же сиквенц на каждой идет с шагом =2
т.е. 1я нода дает значения 1,3,5,7… а 2я нода 2,4,6,8…
Мин-макс. Выше в статье написано, там где про первый байт лонга.
Было бы интересно, если Turbine Inc. разрешит, прочитать про БД в «Властелине Колец Онлайн» который локализовывает ваша контора.
Ну и заодно снова услышать про обновление в марте и почему март длится ТАК долго.
Я с ними никак не связан и ответить не могу.
Андрей, здравствуйте. Вы писали, что у вас бизнес логика(сервер игровой механики) и логика работы с БД(сервер БД) разнесены по разным серверам.

1. Оба сервера написаны на java ?!
2. Какой application server вы используете для сервера игровой механики, и какой для сервера БД?
3. Общение между этими серверами происходит через SOAP сервиса, или Rest?
4. Как вы думаете, связка Jboss для механики и Jetty для сервера БД — хорошее решение?
1. Да
2. Никакого, не очень даже понимаю зачем они нам были бы нужны :)
3. У нас свой протокол и rpc. Бинарный поверх tcp/ip.
4. Не специалист в j2ee, не подскажу.
Андрей, спасибо большое за интересную статью! С нетерпением жду продолжения.

Скажите, пожалуйста, а как вы делаете решардинг? Могут ли пользователи играть во время движения их шардов?
Решардинг в смысле перемещения пользователей между шардами — такого не делаем.
Решардинг в смысле перемещения шардов на другие машины — во время профилактики.
В смысле перемещения шардов между машинами. Перемещаете какими-то скриптами или?
да мы пока не перемещаем. но если надо будет, скриптик напишем.)
Заинтересовал один момент. У нас PostgreSQL используется в проекте с похожими характеристиками с точки зрения количества операций в единицу времени и объема БД. И по факту получается, что 7000 транзакций в секунду (в среднем) превращаются примерно в 600млн транзакций в сутки. А это значит, что каждые, грубо, три дня переполняется счётчик транзакций и база впадает в неизбежный многочасовой VACUUM. При размере БД больше 100ГБ процесс этот тянется медленно и печально. Фактически, некоторые, особо крупные, таблицы практически блокируются на время VACUUM'а. Не сталкивались ли вы с такой проблемой, учитывая, что заметные тормоза в вашем случае, по идее, недопустимы?
Пока не сталкивались, вакуум в бэкграунде успевал всё вычистить.

Если не будет успевать, можно сделать его более злым, можно раскладывать наши базы на большее количество инстансов постгреса, чтобы счётчики транзакций набивались медленнее.
Sign up to leave a comment.