Задать вопрос

Php. Как лучше организовать хранение большого конфига социальной игры и быстрый доступ к нему?

//Апдейт от 17-го июня: решение сформировалось, описание - в конце записи.
//--

Привет!

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

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

Серверная сторона написана на php, использует php-fpm + nginx на входе, percona для холодного хранения данных игроков и Tarantool от mail.ru в виде жирного кэша с актуальными данными (юзеры, играющие в данный момент).

Сначала я хранил конфиг в json, который подгружал в начале обработки скрипта и десериализовывал в ассоциативный массив. Из него брал нужные параметры объектов, в стиле $chickenModel = $globalModelsStorage['Chicken01']
Потом мне показалось, что это долго (unserialize на каждом ходе игрока и хранение здорового массива в памяти) и я заморочился. Пробовал хранить конфиг в виде php-файла, подключаемого include'ом. Тоже показалось долгим (конкретных чисел по результатам теста не помню, увы). Пробовал еще что-то, вглядывался в эту статью - habrahabr.ru/post/112402/.

На данный момент поступаю, как мне кажется, извращенно: храню конфиги в user cache области APC, объекты сериализованы в igbinary. Доступ по ключу к отдельным элементам, быстро и сердито, мне нравится.

Но вот и вопрос:
1. Правильно ли так делать? Можно ли хранить конфиги такого рода в shared memory через APC? Возникнут ли проблемы с потерей данных _в процессе_ работы (я пока таких не отловил, а на случай падения сервака есть скрипт, которые вносит данные конфига обратно в APC)? Насколько это вменяемо и практично?
2. Может мне стоит использовать shared memory в качестве кэша, а в случае, если данные потеряны (невозможно выбрать какой-то параметр по какому-то ключу), брать с диска json и десериализовывать его, затем вносить поправки в кэш в shared memory?
3. Кто как вообще поступает в такой ситуации? Думал посмотреть на Memcached, но, во-первых, при падении так же придется восстанавливать информацию, а во-вторых, так как использую Tarantool, не хотелось бы плодить на сервере зоопарк in-memory софта. Или при моих условиях (memcached только для хранения нескольких тысяч редко меняющихся конфиг-параметров) в этом нет ничего страшного?
Какие еще есть решения? Может, я просто слишком сильно заморачиваюсь на скорости доступа к конфигу?

Заранее спасибо, ну и прошу прощения за сумбурность вопроса.

//Апдейт от 17-го июня:
Провел тесты вариантов pavel_salauyou и VitaZheltyakov. Мне понравился вариант Павла с использованием redis'а, но зачастую в коде сервера мне нужно вытягивать объекты целиком, со всеми их вложенными структурами. Чтобы добиться этого с redis'ом, пришлось бы писать обертку, которая собирает разные пары key-value в единый php-объект, либо как следует переписывать архитектуру сервака.
В итоге храню конфиг в множестве файлов, которые собираю из начального json-конфига не вручную, а автоматизированно. Каждый файл - объект конфига. Инклужу их по мере надобности, всё кэшируется в APC, всё вкусно и быстро.
Спасибо ответившим )
  • Вопрос задан
  • 3735 просмотров
Подписаться 5 Оценить Комментировать
Решения вопроса 1
Если у Вас массив, который редко меняется, то лучше хранить в виде PHP-массива и инклудить его. Опкэшер заберёт этот файл в память и будет Вам счастье.
Такой подход лучше, т.к. нет проблем с кавычками, инклуд происходит максимально быстро.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
pavel_salauyou
@pavel_salauyou
Symfony2 & Angular разработчик
храните весь конфиг в redis, redis хранит данные в оперативной памяти, а так же переодически сохраняет на диск, если что-то пойдёт не так, данные не пропадут.
Ответ написан
lexxpavlov
@lexxpavlov
Программист, преподаватель
Если уж добавлять внешний сервис, то не redis, а MongoDB. Редис - превосходная штука, но Монго умеет нативно хранить вложенные данные - как раз json.
Поэтому для данной задачи Монго подойдёт лучше редиса.
К тому же, Монго так же очень быстра, прекрасно документирована, а также обладает агрегирующими возможностями - можно будет легко делать запросы на сумму, количество и т.п.
Материалов по Монго полно (например, про выборки и изменение данных, а вот о агрегирующих функциях).
Хотя, если вас полностью устраивает решение Виталий Желтяков, то оно лучше, конечно, потому как не привносит новых сущностей в архитектуру проекта. Но если вам нужно делать выборки по конфигу, то подумайте.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы