Как сервер реагирует на выполнение жирных скриптов ?
Делаю игровой проект, где нужно работать со структурой пользователей. А именно:
Первое, что нужно это структура пользователей. Тоесть игроки приглашают других игроков и появляется большое дерево вложенности. К примеру база пользователей будет 1 000 000 пользователей.
Самый оптимальный вариант это использовать технологию дерева вложенности например nested set. Но всеже на такой структуре пересчет ключей занимает длительное время (несколько секунд). По мимо этого мне нужно раздавать бонусы целым структурам. Тоесть если игрок пригласил друго-го игрока, а тот сделал определенное достижение нужно выдавать бонусы всем вышестоящим игрока (родительским элементам текущего).
От сюда выходит так, что скрипт который выдает бонусы к примеру выполняется 20 секунд и по мере увеличения структуры пользователей его время по чуток растет. Тоесть когда пользователь к примеру сделал достижение нужно запустить 20 секундный скрипт, который достанет всех его предков, выдаст им бонусы, запишет историю в общем все оформит как нужно.
Тут у меня возник такой вопрос: что будет если мы запустим скрипт для одного игрока, а во время его выполнения нужно будет запустить скрипт еще для нескольких пользователей. Ну или скажем дойдет до того, что обработка одного игрока будет занимать 20 секунд, а нужно будет обрабатывать по 10 игроков в минуту. Что будет в такой ситуации ? Затормозит ли весь сайт ?
Чуть чуть уточню с чем имеем дело. Все написано на Yii2 и при таких действиях вызывается консольная команда. Еще 1 пример с чем возникнет проблема это с пересчетом ключей. К примеру:
- регистрируется пользователь, я пускаю консольную команду "Обновить структуру", к примеру ключи обновляются 5 секунд. - что будет если зарегистрируются несколько пользователей одновременно ? Правильно ли будут расставлены ключи ?
В общем основная суть вопроса такова, как сервер, php и база данных реагируют на несколько запросов подряд, при этом выполняя все эти скрипты ?
Программист, математик, задрот и даже чуть инженер
Основная проблема будет только с записью. То есть при использовании традиционных SQL можно одним движением руки прострелить себе не то что ноги, но и голову, внезапно обнаружив на себе последствия грязных, фантомных и других чтений.
В плане производительности, нормальный сервер работает как минимум на процессах (cgi-bin), так что все получат хотя бы поровну. Другими словами - если сервер потащит, то задержки будут (если будут) очень небольшими. Асинхронная магия - основное время CPU ожидает, а не числа дробит, отсюда конвейр сможет эффективнее построить цепочку и так далее.
Ну и потом. 10 секунд на миллион пользователей. Много. Слишком. Да и про миллион, товарищ, привираете.
это не пример работающего проекта, это скорее вопрос с примерами цифр для, то чтобы понять как реагирует сервер.
Но я так и не понял 1 момент, к пример если выполняются этот скрипт несколько раз асинхронно, могут ли перемешаться данные ? Ну или может сними случится что то не то ?
@Deerenaros большое спасибо ознакомился с материалом, подчеркнул для себя много нового. Я так понял Gearman сможет решить проблемы с транзакциями ставя их в очередь, это верно ?
Выделите скрипт начисления бонусов в задачу для Gearman. Исходя из того, что вы написали, никакой nested set (я правильно понимаю, это parent_id в записи пользователя ?) вам не нужен - вставляете в строковую колонку ключи всех вышестоящих пользователей в порядке увеличения вложенности через запятую. Обоснованность такого решения - ключи меняться не будут, иерархия часто меняться не будет, удалять записи вы тоже вряд ли будете, скорее, будете их помечать. При изменении иерархии можно эти колонки перестроить, даже простым SQL-запросом. Это даст вам возможность вытаскивать всех вышестоящих пользователей одним запросом. Ни о каких 20 секундах тут даже речи не идет, это будет занимать доли секунды.
Как только появилась необходимость начислить бонусы - отправляете задачу в очередь Gearman-а, основной пул веб-воркеров не занимается ненужной ерундой, готов обрабатывать запросы. Gearman в порядке очереди обрабатывает задачи.
@nepster09 вы имеете в виду иерархию низлежащих элементов дерева для пользователя-родителя? Тогда стоит взять Postgres, там дерево на adjacency list легко и эффективно реализуется с помощью рекурсивных запросов.
Тут можете ознакомиться с основными способами хранения деревьев в реляционных БД habrahabr.ru/post/153861
@AMar4enko да, тоесть в проекте нужно по черному работать со структурой и с родительскими элементами и с дочерними. Также должна быть возможность менять структуры. Это делается не часто, но такая функциональность должна быть.
Во-первых, многое зависит от организации структуры БД. По факту, если руки растут откуда надо и база организована как надо, то ваши 20 секунд отработки - это какое-то фантастически высокое значение.
Во-вторых, про 1 миллион пользователей вы явно нафантазировали.
В-третьих, да тормозить будет всё, если всё находиться на одной машине.
В-четвёртых, установите на прототип проекта xdebug и с помощью трассировки определите точное время работы скрипта и планируемую нагрузку, а не берите цифры с потолка.
кажись при проектировании я следовал всем 5 нормальным формам. Тоесть все должно быть не так уж и плохо. Цифры все с головы, чтобы понять принцип поведения сервера в такой ситуации.