補正トランザクション パターンCompensating Transaction pattern

最終的に整合性がある操作を定義する一連のステップの中で、1 つ以上のステップが失敗した場合に、実行された作業を元に戻します。Undo the work performed by a series of steps, which together define an eventually consistent operation, if one or more of the steps fail. 最終的整合性モデルに従う操作は、複雑なビジネス プロセスとワークフローを実装するクラウド ホスト型アプリケーションでよく見られます。Operations that follow the eventual consistency model are commonly found in cloud-hosted applications that implement complex business processes and workflows.

コンテキストと問題Context and problem

クラウドで実行されるアプリケーションでは、データが頻繁に変更されます。Applications running in the cloud frequently modify data. このデータは、異なる地理的場所に保持されているさまざまなデータ ソースに散在する可能性があります。This data might be spread across various data sources held in different geographic locations. 分散環境で競合を回避しパフォーマンスを向上させるために、アプリケーションは、常にトランザクションの整合性を維持しようと努力すべきではありません。To avoid contention and improve performance in a distributed environment, an application shouldn't try to provide strong transactional consistency. 代わりに、アプリケーションで最終的整合性を実装します。Rather, the application should implement eventual consistency. このモデルでは、一般的なビジネス操作は、一連の独立したステップで構成されます。In this model, a typical business operation consists of a series of separate steps. これらのステップの実行中は、システムの全体的な状態は整合性がないように見えますが、操作が完了してすべてのステップが実行されると、システムは再び整合性のある状態に戻ります。While these steps are being performed, the overall view of the system state might be inconsistent, but when the operation has completed and all of the steps have been executed the system should become consistent again.

分散トランザクションでスケーリングが適切に機能しない理由と最終的整合性モデルの原理に関する情報については、「Data Consistency Primer」(データ整合性入門) を参照してください。The Data Consistency Primer provides information about why distributed transactions don't scale well, and the principles of the eventual consistency model.

最終的整合性モデルの課題は、失敗したステップをどのように処理するかです。A challenge in the eventual consistency model is how to handle a step that has failed. ステップが失敗した場合は、操作内のそれまでのステップによって完了された作業をすべて元に戻す必要が生じることがあります。In this case it might be necessary to undo all of the work completed by the previous steps in the operation. ただし、アプリケーションの他の同時実行インスタンスがデータを変更している場合があるため、データを単純にロールバックすることはできません。However, the data can't simply be rolled back because other concurrent instances of the application might have changed it. 同時実行インスタンスによるデータの変更がない場合でも、ステップを元に戻すことは、単に元の状態を復元するという問題ではないことがあります。Even in cases where the data hasn't been changed by a concurrent instance, undoing a step might not simply be a matter of restoring the original state. 場合によっては、さまざまなビジネス固有の規則を適用する必要があります (「例」セクションで説明する旅行 Web サイトを参照してください)。It might be necessary to apply various business-specific rules (see the travel website described in the Example section).

最終的整合性を実装する操作が複数の異種データ ストアにまたがっている場合、操作内のステップを元に戻すには、各データ ストアに順にアクセスする必要があります。If an operation that implements eventual consistency spans several heterogeneous data stores, undoing the steps in the operation will require visiting each data store in turn. システムに不整合が残らないようにするために、すべてのデータ ストアで実行された作業を確実に元に戻す必要があります。The work performed in every data store must be undone reliably to prevent the system from remaining inconsistent.

最終的整合性を実装する操作によって影響を受けるすべてのデータが、データベースに保持されているわけではありません。Not all data affected by an operation that implements eventual consistency might be held in a database. サービス指向アーキテクチャ (SOA) 環境では、操作によってサービス内のアクションが呼び出され、それによって、そのサービスが保持している状態が変更される可能性があります。In a service oriented architecture (SOA) environment an operation could invoke an action in a service, and cause a change in the state held by that service. この操作を元に戻すには、この状態の変更も元に戻す必要があります。To undo the operation, this state change must also be undone. これを行うには、サービスをもう一度呼び出して、最初のアクションによる影響を逆転させる別のアクションの実行が必要になる可能性があります。This can involve invoking the service again and performing another action that reverses the effects of the first.

解決策Solution

解決策は、補正トランザクションを実装することです。The solution is to implement a compensating transaction. 補正トランザクション内のステップは、元の操作内のステップの影響を元に戻す必要があります。The steps in a compensating transaction must undo the effects of the steps in the original operation. 場合によっては、補正トランザクションは、現在の状態を、操作開始時のシステムの状態に単純に置き換えることはできません。この方法では、アプリケーションの他の同実行インスタンスによって行なわれた変更が上書きされる可能性があるためです。A compensating transaction might not be able to simply replace the current state with the state the system was in at the start of the operation because this approach could overwrite changes made by other concurrent instances of an application. 補正トランザクションは、同時実行インスタンスによって実行されたすべての作業を考慮に入れたインテリジェントなプロセスである必要があります。Instead, it must be an intelligent process that takes into account any work done by concurrent instances. このプロセスは、通常はアプリケーション固有であり、元の操作によって実行される作業の性質に依存します。This process will usually be application specific, driven by the nature of the work performed by the original operation.

一般的な方法は、補正を必要とする最終的に整合性がある操作を実装するワークフローを使用することです。A common approach is to use a workflow to implement an eventually consistent operation that requires compensation. 元の操作が進行するときに、システムは、各ステップに関する情報と、そのステップで実行された作業を元に戻す方法を記録します。As the original operation proceeds, the system records information about each step and how the work performed by that step can be undone. ある時点で操作が失敗した場合、ワークフローは、完了したステップを巻き戻して各ステップを逆転させる作業を実行します。If the operation fails at any point, the workflow rewinds back through the steps it's completed and performs the work that reverses each step. 場合によっては、補正トランザクションは、元の操作と正反対の順序で作業を元に戻す必要がなく、一部の元に戻す操作は並列で実行できます。Note that a compensating transaction might not have to undo the work in the exact reverse order of the original operation, and it might be possible to perform some of the undo steps in parallel.

この方法は、Clemens Vasters のブログで説明されている Sagas 戦略に似ています。This approach is similar to the Sagas strategy discussed in Clemens Vasters’ blog.

補正トランザクションも最終的に整合性がある操作であるため、失敗する可能性があります。A compensating transaction is also an eventually consistent operation and it could also fail. システムは、失敗した時点で補正トランザクションを再開して続行できる必要があります。The system should be able to resume the compensating transaction at the point of failure and continue. 場合によっては、失敗したステップを繰り返して、補正トランザクション内のステップをべき等コマンドとして定義する必要があります。It might be necessary to repeat a step that's failed, so the steps in a compensating transaction should be defined as idempotent commands. 詳細については、べき等パターンに関する Jonathan Oliver のブログを参照してください。For more information, see Idempotency Patterns on Jonathan Oliver’s blog.

失敗したステップからの回復が、手動による介入以外では実行できないことがあります。In some cases it might not be possible to recover from a step that has failed except through manual intervention. この場合、システムはアラートを発生させ、失敗の理由についてできるだけ多くの情報を提供する必要があります。In these situations the system should raise an alert and provide as much information as possible about the reason for the failure.

問題と注意事項Issues and considerations

このパターンの実装方法を決めるときには、以下の点に注意してください。Consider the following points when deciding how to implement this pattern:

最終的な整合性を実装する操作内のステップがいつ失敗したのかを容易に判断できない場合があります。It might not be easy to determine when a step in an operation that implements eventual consistency has failed. 場合によっては、ステップはすぐに失敗するのではなく、ブロックされる可能性があります。A step might not fail immediately, but instead could block. 何らかの形でタイムアウト メカニズムを実装する必要があります。It might be necessary to implement some form of time-out mechanism.

- 補正ロジックの一般化は容易ではありません。-Compensation logic isn't easily generalized. 補正トランザクションは、アプリケーション固有です。A compensating transaction is application specific. 失敗した操作の各ステップの影響を元に戻すには、アプリケーションが十分な情報を持っている必要があります。It relies on the application having sufficient information to be able to undo the effects of each step in a failed operation.

補正トランザクション内のステップは、べき等コマンドとして定義する必要があります。You should define the steps in a compensating transaction as idempotent commands. これにより、補正トランザクション自体が失敗した場合に、ステップを繰り返すことができます。This enables the steps to be repeated if the compensating transaction itself fails.

元の操作内のステップを処理するインフラストラクチャと補正トランザクションは、回復力を持っている必要があります。The infrastructure that handles the steps in the original operation, and the compensating transaction, must be resilient. 失敗したステップを補正するために必要な情報が失われることがなく、補正ロジックの進行状況を確実に監視できる必要があります。It must not lose the information required to compensate for a failing step, and it must be able to reliably monitor the progress of the compensation logic.

補正トランザクションは、システムのデータを常に元の操作の開始時の状態に戻す必要はありません。A compensating transaction doesn't necessarily return the data in the system to the state it was in at the start of the original operation. 代わりに、操作が失敗する前に正常に完了したステップによって実行された作業を補正します。Instead, it compensates for the work performed by the steps that completed successfully before the operation failed.

補正トランザクション内のステップの順序は、必ず元の操作内のステップの正反対の順序にする必要があるわけではありません。The order of the steps in the compensating transaction doesn't necessarily have to be the exact opposite of the steps in the original operation. たとえば、あるデータ ストアのほうが他のデータストアよりも不整合の影響を受けやすい場合は、そのストアに対する変更を元に戻すステップを補正トランザクション内で先に実行する必要があります。For example, one data store might be more sensitive to inconsistencies than another, and so the steps in the compensating transaction that undo the changes to this store should occur first.

操作を完了するために必要な各リソースに短期のタイムアウト ベースのロックを配置して、それらのリソースを事前に取得しておくことで、アクティビティ全体が成功する確率を上げることができます。Placing a short-term timeout-based lock on each resource that's required to complete an operation, and obtaining these resources in advance, can help increase the likelihood that the overall activity will succeed. すべてのリソースが取得された後でのみ、作業を実行する必要があります。The work should be performed only after all the resources have been acquired. ロックが期限切れになる前に、すべてのアクションを終了する必要があります。All actions must be finalized before the locks expire.

補正トランザクションをトリガーするエラーを最小限に抑えるために、通常よりも寛容な再試行ロジックの使用を検討します。Consider using retry logic that is more forgiving than usual to minimize failures that trigger a compensating transaction. 最終的な整合性を実装する操作内のステップが失敗した場合は、エラーを一時的な例外として処理してステップを繰り返すことを試みます。If a step in an operation that implements eventual consistency fails, try handling the failure as a transient exception and repeat the step. ステップが繰り返し失敗するか回復できない場合のみ、操作を停止して補正トランザクションを開始します。Only stop the operation and initiate a compensating transaction if a step fails repeatedly or irrecoverably.

補正トランザクションの実装に関する課題の多くは、最終的整合性を実装するための課題と同じです。Many of the challenges of implementing a compensating transaction are the same as those with implementing eventual consistency. 詳細については、「Data Consistency Primer 」(データ整合性入門) の最終的整合性を実装するための考慮事項に関するセクションを参照してください。See the section Considerations for Implementing Eventual Consistency in the Data Consistency Primer for more information.

このパターンを使用する状況When to use this pattern

このパターンは、失敗した場合は元に戻す必要がある操作に対してのみ使用します。Use this pattern only for operations that must be undone if they fail. 可能であれば、補正トランザクションを必要とする複雑さを持たないようにソリューションを設計します。If possible, design solutions to avoid the complexity of requiring compensating transactions.

Example

旅行 Web サイトで、顧客は旅行プランを予約できます。A travel website lets customers book itineraries. 旅行プランは、一連の航空券とホテルの予約で構成される可能性があります。A single itinerary might comprise a series of flights and hotels. シアトルからロンドンへ、ロンドンからパリに旅行する顧客は、旅行プランを作成するときに次のステップを実行する可能性があります。A customer traveling from Seattle to London and then on to Paris could perform the following steps when creating an itinerary:

  1. シアトルからロンドンへのフライト F1 の座席を予約する。Book a seat on flight F1 from Seattle to London.
  2. ロンドンからパリへのフライト F2 の座席を予約する。Book a seat on flight F2 from London to Paris.
  3. パリからシアトルへの F3 便の座席を予約する。Book a seat on flight F3 from Paris to Seattle.
  4. ロンドンのホテル H1 の部屋を予約する。Reserve a room at hotel H1 in London.
  5. パリのホテル H2 の部屋を予約する。Reserve a room at hotel H2 in Paris.

これらのステップは、最終的に整合性がある操作を構成しますが、各ステップは独立したアクションです。These steps constitute an eventually consistent operation, although each step is a separate action. そのため、システムは、これらのステップを実行するだけではなく、顧客がこの旅行プランをキャンセルした場合に各ステップを元に戻すために必要なカウンター操作も記録しておく必要があります。Therefore, as well as performing these steps, the system must also record the counter operations necessary to undo each step in case the customer decides to cancel the itinerary. カウンター操作を実行するために必要なステップを補正トランザクションとして実行できます。The steps necessary to perform the counter operations can then run as a compensating transaction.

補正トランザクション内のステップの順序は元のステップの正反対ではない場合があること、補正トランザクション内の各ステップのロジックはビジネス固有のルールを考慮に入れる必要があることに注意します。Notice that the steps in the compensating transaction might not be the exact opposite of the original steps, and the logic in each step in the compensating transaction must take into account any business-specific rules. たとえば、ある航空券の予約を取り消しても、支払い済みの費用の全額が顧客に返金されるとは限りません。For example, unbooking a seat on a flight might not entitle the customer to a complete refund of any money paid. 図は、旅行プランを予約するために長時間実行されるトランザクションを元に戻すための補正トランザクションの生成を示しています。The figure illustrates generating a compensating transaction to undo a long-running transaction to book a travel itinerary.

旅行プランを予約するために長時間実行されるトランザクションを元に戻すための補正トランザクションの生成

各ステップに対する補正ロジックの設計方法によっては、補正トランザクション内の手順を並列で実行できる場合があります。It might be possible for the steps in the compensating transaction to be performed in parallel, depending on how you've designed the compensating logic for each step.

多くのビジネス ソリューションでは、1 つのステップの失敗によって、補正トランザクションを使用したシステムのロールバックが常に必要になるわけではありません。In many business solutions, failure of a single step doesn't always necessitate rolling the system back by using a compensating transaction. たとえば、—旅行 Web サイトのシナリオで、顧客が F1 便、F2 便、および F3 便を予約した後で—、ホテル H1 の部屋を予約できなかった場合、望ましいのは航空券の予約を取り消すことではなく、同じ市内にある別のホテルを提案することです。For example, if—after having booked flights F1, F2, and F3 in the travel website scenario—the customer is unable to reserve a room at hotel H1, it's preferable to offer the customer a room at a different hotel in the same city rather than canceling the flights. 顧客はこの旅行プランをキャンセルすると決めることができます (この場合、補正トランザクションが実行され、F1 便、F2 便、および F3 便の予約が元に戻されます) が、この決定は、システムではなく顧客が行う必要があります。The customer can still decide to cancel (in which case the compensating transaction runs and undoes the bookings made on flights F1, F2, and F3), but this decision should be made by the customer rather than by the system.

このパターンを実装する場合は、次のパターンとガイダンスも関連している可能性があります。The following patterns and guidance might also be relevant when implementing this pattern:

  • Data consistency primer (データ整合性入門)Data Consistency Primer. 最終的整合性モデルを実装する操作を元に戻すには、補正トランザクション パターンがよく使用されます。The Compensating Transaction pattern is often used to undo operations that implement the eventual consistency model. この入門では、最終的整合性の利点とトレードオフについて説明します。This primer provides information on the benefits and tradeoffs of eventual consistency.

  • Scheduler-Agent-Supervisor Pattern (スケジューラー - エージェント - スーパーバイザー パターン)。Scheduler-Agent-Supervisor Pattern. 分散型サービスとリソースを使用するビジネス操作を実行する、回復力のあるシステムを実装する方法について説明します。Describes how to implement resilient systems that perform business operations that use distributed services and resources. 場合によっては、操作によって実行された作業を補正トランザクションを使用して元に戻す必要があります。Sometimes, it might be necessary to undo the work performed by an operation by using a compensating transaction.

  • 再試行パターンRetry Pattern. 補正トランザクションの実行は負荷が高くなる可能性があり、場合によっては、失敗した操作を再試行パターンに従って再試行する有効なポリシーを実装することによって、その使用を最小限に抑えることができます。Compensating transactions can be expensive to perform, and it might be possible to minimize their use by implementing an effective policy of retrying failing operations by following the Retry pattern.