Как избежать двойной обработки данных на загруженном сайте? - PullRequest
0 голосов
/ 26 января 2011

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

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

Пример того, что может произойти:

  • Мы ждем 20 человек, чтобы добавить элемент в свой список желаний, и у нас есть 19.
  • Боб и Салли заходят на сайт и нажимают кнопку «добавить в список желаний»
  • Сервер получает запрос Боба, видит, что теперь выполнено 20 запросов, и взимает плату.
  • В то жеКогда сервер получает запрос Салли и все еще видит 19 запросов в дБ с момента одновременного получения заказа Боба, начинает обрабатывать платежи.Следовательно, платежи взимаются дважды.

Есть идеи, как этого избежать?

Я использую базу данных MySQL и PHP для программирования.

Ответы [ 2 ]

1 голос
/ 27 января 2011

Это тип вещи, для которой предназначены транзакции.Зарядка карточек и сброс счетчика wislist должны выполняться в одной транзакции, чтобы они выполнялись как атомная единица.Кроме того, чтобы избежать описываемой проблемы, необходимо установить уровень изоляции транзакции как минимум «Read Committed» «Repeatable Read».

Дополнительная информация:

Вот как это сделать: 1. Приложение открывает транзакцию в базе данных.2. Приложение делает выбор в таблицах желаний, чтобы получить количество.3. Если счетчик> = n, приложение делает другой выбор в списке пожеланий и связанных таблицах, чтобы получить ожидающие заказы в списке желаний, пользователей, информацию о карте и т. Д. 4. В зависимости от бизнес-правил, касающихся транзакций по карте, приложение затем удаляетотложенные ордера или что угодно, чтобы сбросить список желаний до нуля.5. Затем приложение закрывает транзакцию.

Вот почему это работает: когда приложение делает выбор в таблицах списков пожеланий, чтобы получить счетчик внутри транзакции, БД устанавливает блокировку чтения для таблиц, связанных с этим.запрос.Если другая транзакция, которая открылась во время ожидания предыдущей транзакции, пытается прочитать те же самые таблицы, она должна дождаться, пока предыдущая транзакция не получит COMMIT или ROLLBACK.Если предыдущая транзакция COMMITS, то следующая транзакция увидит счет 0 и все остальные модификации.В противном случае, если приложение выполнит ROLLBACK по какой-либо причине, ни одно из данных не изменится и следующая транзакция увидит данные такими, какими они были до первой транзакции.

0 голосов
/ 26 января 2011

Я делаю похожий сайт в данный момент. Кажется популярным ...

Важно, чтобы ваши процессы были идемпотентными. В этом контексте это означает, что если вы запускаете нашу службу начисления несколько раз, заказы, которые уже были оплачены, не оплачиваются дважды.

Я выполняю это, устанавливая для OrderStatus значение «NotProcessed» при размещении заказа. После запуска службы и оплаты заказа OrderStatus изменяется на «PaymentPending». Я взимаю плату за заказ, только если OrderStatus имеет статус «Не обработан».

КОД PSEUDO:

void ProcessPendingOrders()
{
   var orders = getAllOrders();
   foreach(Order order in orders)
   {
    if (order.OrderStatus == NotProcessed)
       ChargeOrder(order)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...