Compensating Transaction pattern
Отмените работу, выполняемую серией шагов, которые вместе определяют согласованную операцию, если один или несколько шагов не выполняются. Операции, которые следуют за конечной моделью согласованности, обычно встречаются в облачных приложениях, которые реализуют сложные бизнес-процессы и рабочие процессы.
Контекст и проблема
Приложения, работающие в облаке, часто изменяют данные. Эти данные могут распространяться на различные источники данных, хранящиеся в разных географических точках. Чтобы избежать конкуренции и повышения производительности в распределенной среде, приложение не должно пытаться обеспечить надежную последовательность транзакций. Скорее, приложение должно реализовать конечную согласованность. В этой модели типичная бизнес-операция состоит из серии отдельных шагов. Хотя эти шаги выполняются, общий вид состояния системы может быть непоследовательным, но когда операция завершена и все шаги были выполнены, система должна снова стать последовательной.
В «Руководстве по согласованности данных (Data Consistency Primer)» содержится информация о том, почему распределенные транзакции недостаточно масштабируются, а также принципы модели конечной согласованности.
Задача в модели возможной согласованности заключается в том, как справиться с неудачным шагом. В этом случае может потребоваться отменить всю работу, выполненную с помощью предыдущих шагов операции. Однако данные нельзя просто отменить, поскольку другие параллельные экземпляры приложения могли бы изменить его. Даже в тех случаях, когда данные не были изменены параллельным экземпляром, отмена шага может быть не просто вопросом восстановления исходного состояния. Возможно, потребуется применять различные правила для бизнеса (см. Веб-сайт путешествия, описанный в разделе «Пример»).
Если операция, которая реализует конечную согласованность, охватывает несколько разнородных хранилищ данных, отмена шагов в операции требует поочередного посещения каждого хранилища данных. Работа, выполняемая в каждом хранилище данных, должна быть отменена, чтобы система не оставалась непоследовательной.
Не все данные, затронутые операцией, которая реализует возможную согласованность, могут храниться в базе данных. В среде, ориентированной на сервис-ориентированную архитектуру (SOA), операция может вызывать действие в службе и вызывать изменение состояния, поддерживаемого этой службой. Чтобы отменить операцию, это изменение состояния также должно быть отменено. Это может включать повторный вызов службы и выполнение другого действия, которое отменяет эффекты первого.
Решение
Решение заключается в реализации компенсирующей транзакции. Шаги в компенсирующей транзакции должны отменять действие шагов в исходной операции. Компенсационная транзакция может оказаться неспособной просто заменить текущее состояние на состояние, в котором находилась система в начале операции, потому что этот подход может перезаписать изменения, сделанные другими параллельными экземплярами приложения. Вместо этого он должен быть интеллектуальным процессом, который учитывает любую работу, выполняемую параллельными экземплярами. Этот процесс обычно будет специфичным для приложения, определяемым характером работы, выполняемой исходной операцией.
Общим подходом является использование рабочего процесса для реализации последовательной операции, требующей компенсации. По мере выполнения исходной операции система записывает информацию о каждом шаге и о том, как можно выполнить работу, выполненную на этом шаге. Если операция завершается с ошибкой в любой момент, рабочий процесс перематывается назад по этапам, которые он завершил, и выполняет работу, которая меняет каждый шаг. Обратите внимание, что компенсационная транзакция, возможно, не должна отменять работу в точном обратном порядке исходной операции, и может быть возможно выполнить некоторые из шагов отмены в параллельном режиме.
Этот подход аналогичен стратегии Sagas, обсуждаемой в блоге Clemens Vasters .
Компенсационная транзакция также является последовательной операцией, и она также может потерпеть неудачу. Система должна иметь возможность возобновить компенсационную транзакцию в точке отказа и продолжить. Возможно, потребуется повторить неудавшийся шаг, поэтому шаги в компенсирующей транзакции должны быть определены как команды идемпотента. Дополнительную информацию см. В разделе «Идемпотентные шаблоны» в блоге Джонатана Оливера.
В некоторых случаях может оказаться невозможным восстановление с шага, который провалился, за исключением ручного вмешательства. В этих ситуациях система должна поднять оповещение и предоставить как можно больше информации о причине отказа.
Проблемы и соображения
При принятии решения о реализации этого шаблона рассмотрите следующие моменты:
Было бы нелегко определить, произошел ли сбой в операции, которая реализует конечную согласованность. Шаг может не сработать немедленно, но вместо этого он может блокироваться. Возможно, потребуется реализовать какой-то механизм тайм-аута.
-Компенсационная логика не просто обобщается. Компенсационная транзакция является специфичной для приложения. Он полагается на приложение, имеющее достаточную информацию, чтобы иметь возможность отменить эффекты каждого шага в неудавшейся операции.
Вы должны определить шаги в компенсирующей транзакции как команды idempotent. Это позволяет повторять шаги, если сама компенсационная транзакция терпит неудачу.
Инфраструктура, которая обрабатывает шаги в исходной операции и компенсирующую транзакцию, должна быть устойчивой. Он не должен терять информацию, необходимую для компенсации неудачного шага, и должен быть способен надежно контролировать ход логики компенсации.
Компенсационная транзакция не обязательно возвращает данные в системе в состояние, в котором оно находилось в начале первоначальной операции. Вместо этого он компенсирует работу, выполненную с помощью шагов, которые успешно завершились до того, как операция завершилась неудачно.
Порядок шагов в компенсирующей транзакции необязательно должен быть полностью противоположным шагам в исходной операции. Например, одно хранилище данных может быть более чувствительным к несоответствиям, чем другое, и поэтому сначала должны выполняться шаги в компенсирующей транзакции, которые отменят изменения в этом хранилище.
Размещение кратковременного тайм-аута на каждом ресурсе, которое требуется для завершения операции, и получение этих ресурсов заблаговременно, может помочь повысить вероятность успеха всей деятельности. Работу следует выполнять только после того, как все ресурсы были приобретены. Все действия должны быть завершены до истечения срока действия замков.
Подумайте, используя логику повтора, которая более прощает, чем обычно, для минимизации сбоев, которые вызывают компенсационную транзакцию. Если какой-либо шаг в операции, которая реализует конечную согласованность, сработает, попробуйте обработать отказ в качестве исключения переходного процесса и повторите шаг. Только прекратите операцию и инициируйте компенсационную транзакцию, если шаг прерывается многократно или безвозвратно.
Многие проблемы реализации компенсирующей транзакции такие же, как и при реализации возможной последовательности. Дополнительную информацию см. В разделе «Соображения для реализации окончательной согласованности в Primary Primary Primerity» .
Когда использовать этот шаблон
Используйте этот шаблон только для операций, которые необходимо отменить, если они не сработают. Если возможно, проектные решения избегают сложностей, требующих компенсации транзакций.
Пример
Веб-сайт путешествия позволяет клиентам забронировать маршруты. Один маршрут может включать в себя ряд рейсов и отелей. Клиент, путешествующий из Сиэтла в Лондон, а затем в Париж, мог выполнить следующие шаги при создании маршрута:
- Закажите место в полете F1 из Сиэтла в Лондон.
- Закажите место на рейсе F2 из Лондона в Париж.
- Закажите место на рейсе F3 из Парижа в Сиэтл.
- Забронировать номер в отеле H1 в Лондоне.
- Забронируйте номер в отеле H2 в Париже.
Эти шаги представляют собой последовательную операцию, хотя каждый шаг является отдельным действием. Поэтому, а также выполнение этих шагов, система должна также записывать операции счетчика, необходимые для отмены каждого шага, если клиент решает отменить маршрут. Затем шаги, необходимые для выполнения операций счетчика, могут выполняться как компенсационная транзакция.
Обратите внимание, что шаги в компенсирующей транзакции могут быть не полностью противоположными исходным шагам, а логика на каждом этапе компенсирующей транзакции должна учитывать любые бизнес-правила. Например, исключение места в полете может не дать клиенту полного возмещения любых уплаченных денег. На рисунке показано создание компенсирующей транзакции, чтобы отменить долгосрочную транзакцию, чтобы забронировать маршрут путешествия.
Возможно, что шаги в компенсирующей транзакции будут выполняться параллельно, в зависимости от того, как вы разработали компенсационную логику для каждого шага.
Во многих бизнес-решениях отказ одного шага не всегда требует возврата системы обратно с помощью компенсирующей транзакции. Например, если после бронирования полетов F1, F2 и F3 в сценарии веб-сайта путешествия — клиент не может зарезервировать номер в отеле H1, предпочтительнее предложить клиенту комнату в другом отеле в том же городе, а чем отмена рейсов. Клиент все же может решить отменить (в этом случае выполняется компенсационная транзакция и отменяет заказы, сделанные на рейсах F1, F2 и F3), но это решение должно приниматься клиентом, а не системой.
Связанные шаблоны и руководство
При реализации этого шаблона также могут иметь значение следующие шаблоны и рекомендации:
- Data Consistency Primer . Шаблон компенсационной транзакции часто используется для отмены операций, реализующих модель конечной согласованности. Этот праймер предоставляет информацию о преимуществах и компромиссах возможной последовательности.
- Шаблон планировщика-агента-супервизора . Описывает, как внедрять отказоустойчивые системы, которые выполняют бизнес-операции, которые используют распределенные сервисы и ресурсы. Иногда может потребоваться отменить работу, выполняемую операцией, с помощью компенсирующей транзакции.
-
Повторите шаблон . Компенсация транзакций может быть дорогостоящей, и можно было бы свести к минимуму их использование путем реализации эффективной политики повторных неудачных операций, следуя шаблону Retry.
Original(english): https://docs.microsoft.com/en-us/azure/architecture/patterns/compensating-transaction
Translation: Basic, need improvement
Status: Draft
Action: Vote to improve