Snickersmix
@Snickersmix
Web-разработчик

Как предотвратить параллельное выполнение запросов пользователя?

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

Как осуществить некую блокировку для конкретного пользователя чтобы следующий запрос не выполнялся пока не отработает предыдущий без ограничений на отправку со стороны клиента?
  • Вопрос задан
  • 171 просмотр
Решения вопроса 1
Snickersmix
@Snickersmix Автор вопроса
Web-разработчик
Решилось все стандартными средствами php.
Когда мы открываем сессию, то до её закрытия php не открывает параллельную сессию с таким же названием до тех пор пока мы не закроем текущую. Закрыть можно так же во время выполнения скрипта до его завершения php.net/manual/en/function.session-write-close.php.
По умолчанию имя сессии приходит вместе с запросом, php сам устанавливает соответсвующую куку.
У меня случай когда сессий может быть несколько или вовсе не быть сессии для одного пользователя, поэтому я после авторизации задаю своё название для сессии из id пользователя + соли
session_id(hash('sha256',$userId+$salt);
В моем случае все запросы проходят через авторизацию пользователя и у меня всегда есть id пользователя
После я запускаю сессию
session_start()
И теперь все запросы от пользователя будут ожидать завершения текущего запроса и далее по очереди.

Этот же механизм можно сделать и через php.net/manual/en/function.flock.php как писал lusin , но тогда нам придется самим заботиться о хранилище лок файлов, проверки снятия лока, сборке мусора и т.д.
В случае когда нужно дождаться какого то общего лока который растягивается на несколько пользователей, в таком случае нам уже придется пользоваться php.net/manual/en/function.flock.php либо блокировкой таблицы или строки как предложил Rsa97 .
В данном же случае было достаточно использовать стандартный механизм сессий
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Обычное состояние гонки. Решается, например, блокировкой таблицы или строки.
Ответ написан
Комментировать
@AUser0
Чем больше знаю, тем лучше понимаю, как мало знаю.
При обновлении счётчика добавить условие, что значение счётчика равно значению при начале выполнения кода.
UPDATE `table` SET counter=3 WHERE id='XXX' AND counter='4';
Ответ написан
Комментировать
lusin
@lusin
В дополнение к написанному выше, из коробки PHP можно использовать flock php.net/manual/en/function.flock.php . Если разрабатываете с использованием фреймворка, скорее всего, имеется прикладное решение.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы