Как бороться с бестранзакционным обслуживанием во время транзакции?

Предположим, у меня есть SQL-транзакционная финансовая система, но во время транзакции она вызывает внешний не-SQL сервис.

Что делать, например, с потеря питания, когда у нас нет, был ли внешний вызов успешным или нет?

Представим, что на SQL-базе данных и биткойн-кошельке совершается транзакция.

  1. Начать SQL-транзакцию
  2. Уменьшить количество наличных денег пользователя
  3. Отправляйте пользовательские деньги куда-нибудь через биткойн-кошелек
  4. Совершить

Потеря мощности между шагами 3 и 4 предотвратит транзакцию (без уменьшения наличных денег пользователя), но фактически отправит наши деньги из кошелька.

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

В настоящее время я уменьшаю деньги и помечаю транзакцию как «в процессе» (и фиксирую это) перед вызовом внешней службы, затем, если внешняя служба отвечает «ОК», я отмечаю все как успешно завершенное.

Но при потере питания я все еще могу оставаться в ситуации, когда какая-то транзакция после отключения питания помечается как «в процессе», деньги уменьшаются, но я должен вручную смотреть транзакции биткойн-кошелька/блокчейна, действительно ли деньги были отправлены.

Есть ли лучший способ управлять транзакциями в этой ситуации? Можно ли как-то решить без возможности проверить в будущем, был ли наш внешний вызов успешным или нет? (например, я могу проверить все прошлые транзакции в блокчейне)


person Piotr Müller    schedule 18.06.2014    source источник


Ответы (1)


Добро пожаловать в удивительный мир распределенных транзакций! Поработав над ними в течение многих лет в разных местах (MS, Google и т. д.), Пэт Хелланд пришел к выводу, что не существует серебряной пули и что лучшее, что вы можете сделать, — Последовательность'.

Вы делаете хорошее начало с флагом «Выполняется». Не зная деталей удаленной транзакции (то есть, какие шаги вы должны пройти, какие данные доступны по завершении каждого), я не могу сказать вам, как именно это сделать, поэтому вот некоторые общие положения.

Если вы можете получить идентификатор транзакции с удаленного сайта до того, как транзакция будет зафиксирована, то, когда вы его получите, обновите локальную базу данных с помощью этого идентификатора транзакции. Когда удаленная транзакция будет завершена, обновите флаг «Завершено» в вашей локальной базе данных.

Теперь у вас будет несколько возможных состояний. Внимания требуют только два:

  1. InProgress установлено, не завершено, нет TransactionId: транзакция remnote должна быть запущена и завершена
  2. InProgress установлен, не завершен, идентификатор транзакции существует: может быть зафиксирован на удаленном сайте; связаться с ним, чтобы проверить, была ли завершена эта транзакция; если не завершено (или вернуться к первому состоянию и сделать все)

Это план. Как я уже сказал, я не знаю всех подробностей о том, как завершается биткойн-транзакция, но я надеюсь, что это даст вам представление.

person simon at rcl    schedule 18.06.2014