Две транзакции с одинаковыми номерами квитанций - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть платежная система, для которой я генерирую номер квитанции (который работает с шагом) для каждой транзакции.Процесс подобен тому, как когда пользователь нажал на оплату, запрос отправляется на сервер, который выбирает последний номер квитанции из базы данных, увеличивает его на 1, затем немедленно сохраняет его в базе данных для дальнейших транзакций и так далее.Номера квитанций генерируются в формате xx000001, где xx - символы.

Проблема : - Иногда две или более транзакций обрабатываются с одним и тем же номером квитанции.

Возможный сценарий : - Сценарий, который я придумал, похож на - Предположим, кто-то нажал, а затем сервер извлекает последний номер квитанции, в то время как сервер делает приращение, пришла новая транзакция и получает тот же номер квитанции, что и предыдущий, и обаони делают приращение и получают тот же номер чека для обработки.

Любая помощь будет принята с благодарностью !!!

Спасибо

1 Ответ

0 голосов
/ 20 сентября 2018

Звучит как классическая проблема: у вас нет безопасности потоков!Параллельные запросы (и серверы http , как правило, обрабатывает параллельные запросы, должны быть реализованы таким образом, чтобы критические шаги (которые могли привести к коллизиям) препятствовали выполнению параллельно.1006 * У вас есть несколько вариантов решения этой проблемы:

  1. для обеспечения безопасности потоков в вашей логике

позаботьтесь о создании какой-либо формы блокировки, которая препятствует обработке нескольких процессовсразу, хотя только для критического шага, здесь приращение этого счетчика. 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»), вам необходимо реализовать дополнительный диспетчер блокировок на основе одного процесса (например, менеджер очередей, упомянутый выше),Так что-то вроде микросервиса вы используете внутри.Мне не кажется, что это стоит хлопот: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...