PHP, выполнение действия единоразово при условии многократного, единовременного обращения пользователей?
Всем доброго времени суток.
Есть онлайн игра, играет между собой например 10 человек, от каждого раз в секунду идут аякс запросы к серверу для получения изменений игры, в какой-то момент, например по завершению хода надо посчитать и начислить очки игрокам, проблема в том что при проверке, были ли уже начислены очки за этот ход, могут единовременно сработать 2-3 запроса, получив из базы инфу что очки еще не начислены и 2-3 раза начислить очки игрокам.
Решил проблему так: сначала пауза рандомом от 0 до 2.5 сек (дабы минимизировать вероятность одновременного выполнения), потом делаю запрос в БД с проверкой - была ли запись, если нет то ставлю отметку что была и считаю очки и начисляю. Такой алгоритм решил проблему полностью, но он все-таки кривой, интересно узнать какие методы решения существуют, т.е. мне надо выполнить действие гарантированно один раз при одновременном обращении к скрипту 10-20 человек
DTX: Один и тот же скрипт может выполняться одновременно, когда Вы обращаетесь к php скрипту (сайту) Вы же не ждете пока он отработает у всех других пользователей
DTX: если апач под виндой - то да, ждете, в остальных вменяемых конфигурациях веб-серверов - не ждете, максимальное кол-во одновременных подключений (параллельных выполнений) регулируется настройками веб-сервера
У вас в принципе архитектура кривая. Игру проще всего делать, когда инициатором получения изменений является сервер (через WebSockets, например). Тогда никакие действия не нужно будет делать несколько раз - посчитали => сформировали событие => разослали его всем подписчикам. А клиент уже только реагирует на эти изменения.
Игра в браузере, держать соединение сокетами каким образом, скриптом на том же сервере и из браузера слать аяксы к нему? Нет, это как-то не то, архитектура простая, игрок что-то сделал - аякс запрос на сервер, у всех остальных постоянный запрос обновил сведения о действии, потом в определенный момент, через 15 секунд после выполнения условия (например все сделали ход), надо считать очки, вот при постоянном обращении мы смотрим - если прошло 15 секунд и очки еще не подсчитаны - надо посчитать.... Ну а вообще я пытаюсь понять в какую сторону гуглить, т.к. уверен должны быть библиотеки для построения очередей заданий, что-то вроде планировщика
Из браузера не нужно слать никакие ajax-запросы, в этом весь смысл. Вся работа происходит на сервере, а клиенты имеют к нему постоянное подключение и сразу автоматически узнают обо всех изменениях. И ваша проблема просто исчезает, она в принципе не может возникнуть при такой архитектуре.
Такая архитектура имеет свои минусы например при обрыве связи\интернета, вообще я спрашивал решение моей проблемы, а не как перепилить архитектуру, кстати ответ найден и существует давно, для таких "неправильных" архитектур как у меня, оказывается, существуют решения, вот то о чем я спрашивал - https://habrahabr.ru/post/56578/
Решение вашей проблемы - не создавать проблему изначально. Да, менять архитектуру сложно и не всегда возможно. Именно поэтому я и написал ответ - и вы в будущих проектах будете знать, что так лучше не делать и другие люди, которые только начинают аналогичный проект.
- Доктор, пропишите мне какое-нибудь хорошее средство от синяков.
- А что случилось?
- Понимаете, когда мне нужно повернуть голову, я бью себя в скулу кулаком. Поначалу нормально, но потом образуется синяк и бить становится всё больнее.
- Хм, может, вам просто пользоваться шеей? Она для этого подходит гораздо лучше. Зачем создавать себе проблемы на пустом месте?
- Вы нашли ответ на каждый вопрос этой поликлиники, спасибо, кэп!
Кирилл Леванов: проблемы с обрывом связи нет, это достаточно просто решается, если вести учет номеров сообщений (достаточно хранить в памяти демона небольшой кусок) и знать на клиенте последний полученный.
Если же нужно получить достоверную информацию в произвольный момент времени, то всегда есть возможность запросить состояние командой через тот же ajax.
akubintsev: и Вам советую посмотреть сюда https://habrahabr.ru/post/56578/
Каждый предлогает и хвалит то что умеет, а вот ответить на вопрос - смог один человек, четко и по теме, а решение переделать - каждый может предлагать
akubintsev: там в статье все примитивы на синхронной очереди построены.
Кирилл Леванов: удалённый комментарий, вы, видимо, мне писали. Отвечу. Ещё раз - в своём ответе я показал один из вариантов решения вашей задачи. То, что он не подходит конкретно вам в конкретно этом случае, не значит ровным счётом ничего - в вопрос придут другие люди, которым мой ответ не наступить на те же грабли, что и вы.
Алексей Уколов: ему "решение с мьютексом" ничем не поможет судя по тому, что информация в игре циркулирует через ajax-запросы. То есть демона нет в принципе. Всё, что он сможет сделать, это сделать блокировки через хранилище, типа БД или memcache. Никакие мьютексы тут нафиг не нужны.
Кирилл: все это опять же про демонов. У меня есть подозрение, что вы не разобрались еще что это и чем работа php в CLI отличается от работы веб-сервера. Именно этот пробел и нужно восполнить прежде, чем решать вопросы межпоточной и межпроцессной синхронизации.