Звучит как классическая проблема: у вас нет безопасности потоков!Параллельные запросы (и серверы http , как правило, обрабатывает параллельные запросы, должны быть реализованы таким образом, чтобы критические шаги (которые могли привести к коллизиям) препятствовали выполнению параллельно.1006 * У вас есть несколько вариантов решения этой проблемы:
- для обеспечения безопасности потоков в вашей логике
позаботьтесь о создании какой-либо формы блокировки, которая препятствует обработке нескольких процессовсразу, хотя только для критического шага, здесь приращение этого счетчика. php
не предлагает что-то вроде ключевого слова java synchronized
, которое делает именно это, так что вы должны реализовать это самостоятельно. Самым простым будет либо классический unixкак файл блокировки на основе файловой системы: процесс, который должен иметь уникальный доступ, запрашивает файл блокировки. Если он не еще существует, он генерируется (обычно с идентификатором процесса в качестве содержимого), и процесс выполняет свое действиепока он не закончил и не позаботился оk снова / снова удалите файл блокировки.Только тогда второй процесс может создать этот файл, пока он не будет заблокирован (зависает).Попытки получить уникальный журнал могут быть реализованы либо с помощью примитивной стратегии опроса, поэтому запрос на получение блокировки повторяется каждые несколько сотен миллисекунд, либо вы реализуете систему очередей, которая также может позаботиться о сохранении запрашивающих процессов в определенном порядке:обработки и которые могут позаботиться о процедурах очистки, таких как удаление устаревших файлов блокировки (после того, как что-то сломалось или устарело).
используйте семафоры для блокировки
так же, как и выше, но вы полагаетесь на "семафоры" php для реализации самой блокировки: http://php.net/manual/en/ref.sem.php
использовать блокировку таблицы внутри базы данных
так же, как описано выше, но вы полагаетесь на функцию блокировки ядра базы данных (зависит от типа используемого вами механизма базы данных).В конце концов, это быстрее и проще реализовать, так как вам все равно нужно взаимодействовать с базой данных.
использовать хранимые процедуры
вы также можете перемещать критические части в хранимые процедуры внутри базы данных.Это позволяет выполнять необходимые шаги внутри одной транзакции базы данных, которая в соответствии с определением гарантированно либо полностью, либо вообще не выполняется.Таким образом, вы генерируете новый идентификатор в качестве первичного ключа в вашей таблице счетчиков.Когда вы затем используете этот ключ для дальнейших запросов (вставок) в той же транзакции , которую вы выполняете в database_, тогда вы в безопасности, поскольку любая попытка зафиксировать транзакцию приводит к коллизии первичного ключа.быть отклоненным базой данных.В этом случае вы можете просто начать процесс заново.
используйте расширение
sync
PECL
Существует расширение PECL для php
, которое предлагает нечто сопоставимое с ключевым словом synchronized
java:
http://php.net/manual/en/threaded.synchronized.php
Это позволяет использовать механизм блокировки прямо внутри вашего php-кода.Но вам нужно иметь один процесс, чтобы это работало, так что это зависит от настроек вашего рабочего в среде http-сервера.Если вы полагаетесь на основанную на потоках рабочую модель для php (все запросы php обрабатываются в одном процессе, но в нескольких потоках), то вы готовы к работе.Однако, если вы используете многопроцессорную рабочую модель (как обычно это делается с помощью «prefork php module» или «быстрого контейнера cgi»), вам необходимо реализовать дополнительный диспетчер блокировок на основе одного процесса (например, менеджер очередей, упомянутый выше),Так что-то вроде микросервиса вы используете внутри.Мне не кажется, что это стоит хлопот: -)