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

Azure

一連のステップで構成される最終的に整合性がある操作を使用するときは、補正トランザクション パターンが役立ちます。 具体的には、1 つ以上のステップが失敗した場合、補正トランザクション パターンを使用して、ステップで実行された作業を元に戻すことができます。 通常、最終的整合性モデルに従う操作は、複雑なビジネス プロセスとワークフローを実装するクラウド ホスト型アプリケーションで見受けられます。

コンテキストと問題

クラウドで実行されるアプリケーションでは、データが頻繁に変更されます。 このデータは、異なる地理的場所にあるさまざまなデータ ソースに散在している場合があります。 分散環境で競合を回避しパフォーマンスを向上させるために、アプリケーションは、常にトランザクションの整合性を維持しようと努力すべきではありません。 代わりに、アプリケーションで最終的整合性を実装します。 最終的整合性モデルでは、一般的なビジネス操作は一連の独立したステップで構成されます。 操作でこれらのステップが実行されている間、システム状態を全体的に見ると整合性がないことがあります。 ただし、操作が完了し、すべてのステップが実行されると、システムは整合性を取り戻します。

分散トランザクションでスケーリングが適切に機能しない理由については、「データ整合性入門」を参照してください。 このリソースには、最終的整合性モデルの原理も一覧で示されています。

最終的整合性モデルの課題は、失敗したステップをどのように処理するかです。 エラーが発生すると、操作の前のステップで完了したすべての作業を元に戻す必要が生じる場合があります。 ただし、データは、アプリケーションの他の同時実行インスタンスによって変更されている場合があるため、常にロールバックできるとは限りません。 同時実行インスタンスによってデータが変更されていないときでも、ステップを元に戻すことは元の状態を復元するより複雑な場合があります。 さまざまなビジネス固有のルールを適用することが必要になる場合があります。 例については、この記事の後半の「」セクションで説明する旅行の Web サイトを参照してください。

最終的整合性を実装する操作が複数の異種データ ストアにまたがっている場合、操作内のステップを元に戻すには、各データ ストアに順にアクセスする必要があります。 システムに不整合な点を残さないようにするには、すべてのデータ ストアで実行した作業を確実に元に戻す必要があります。

最終的整合性を実装する操作の影響を受けるデータが、常にデータベースに保持されているとは限りません。 たとえば、サービス指向アーキテクチャ (SOA) 環境について考えてみます。 SOA 操作によってサービス内のアクションが呼び出され、それが原因でそのサービスによって保持されている状態が変化することがあります。 この操作を元に戻すには、この状態変更も元に戻す必要があります。 このプロセスでは、サービスをもう一度呼び出して、最初のアクションによる影響を逆転させる別のアクションの実行が必要になる可能性があります。

解決策

解決策は、補正トランザクションを実装することです。 補正トランザクション内のステップは、元の操作内のステップの影響を元に戻します。 直感的な方法として、現在の状態を、操作の開始時にシステムが置かれていた状態に置き換えます。 ただし、補正トランザクションで常にその方法を実施できるとは限りません。それによって、アプリケーションの他の同時実行インスタンスで行われた変更が上書きされる可能性があるためです。 むしろ、補正トランザクションは、同時実行インスタンスによって行われる作業を考慮したインテリジェントなプロセスでなければなりません。 このプロセスは、通常はアプリケーション固有であり、元の操作によって実行される作業の性質に依存します。

一般的な方法は、補正を必要とする最終的に整合性がある操作を実装するワークフローを使用することです。 元の操作が進行する中で、ステップで実行された作業を元に戻す方法など、各ステップに関する情報がシステムによって記録されます。 ある時点で操作が失敗した場合、ワークフローでは、完了したステップを巻き戻します。 ワークフローでは、ステップごとに、そのステップを逆にする作業を実行します。

2 つの重要点を次に示します。

  • 補正トランザクションでは、必ずしも元の操作の正反対の順序で作業を元に戻すとは限りません。
  • 元に戻すステップをいくつか並列で実行できることがあります。

この方法は、Clemens Vasters のブログで説明されている Sagas 戦略に似ています。

補正トランザクションはそれ自体が最終的に整合性がある操作であるため、失敗することもあります。 システムは、失敗した時点で補正トランザクションを再開して続行できる必要があります。 失敗したステップを繰り返すことが必要になる場合があるため、補正トランザクション内のステップを羃等コマンドとして定義する必要があります。 詳細については、べき等パターンに関する Jonathan Oliver のブログを参照してください。

場合によっては、手動介入のみが、失敗したステップから回復する方法であることがあります。 この場合、システムはアラートを発生させ、失敗の理由についてできるだけ多くの情報を提供する必要があります。

問題と注意事項

このパターンの実装方法を決めるときには、以下の点に注意してください。

  • 最終的整合性を実装する操作内のステップがいつ失敗したのかを容易に判断できない場合があります。 ステップはすぐに失敗しない場合があります。 代わりに、ブロックされることがあります。 タイムアウト メカニズムの実装が必要になる場合があります。

  • 補正ロジックは簡単に一般化できません。 補正トランザクションは、アプリケーション固有です。 失敗した操作の各ステップの影響を元に戻すには、アプリケーションが十分な情報を持っている必要があります。

  • 補正トランザクション内のステップは、べき等コマンドとして定義する必要があります。 それにより、補正トランザクション自体が失敗した場合に、ステップを繰り返すことができます。

  • ステップを処理するインフラストラクチャは、次の条件を満たしている必要があります。

    • 元の操作および補正トランザクション内で回復性がある。
    • 失敗したステップを補うために必要な情報を失わない。
    • 補正ロジックの進行状況を確実に監視する。
  • 補正トランザクションでは、システムのデータを必ずしも元の操作の開始時の状態に戻すわけではありません。 代わりに、このトランザクションでは、操作が失敗する前の、正常に完了したときの作業を補正します。

  • 補正トランザクション内のステップの順序は、必ずしも元の操作内のステップの正反対にする必要はありません。 たとえば、あるデータ ストアは、不整合による影響を別のものより大きく受ける場合があります。 このストアに対する変更を取り消す補正トランザクションのステップは、最初に実行する必要があります。

  • 特定の対策を行うと、全体的なアクティビティが成功する可能性が高まる場合があります。 具体的には、操作の完了に必要な各リソースに対して、短期のタイムアウト ベースのロックを設定できます。 これらのリソースは、事前に取得することもできます。 その後、すべてのリソースを取得した後にのみ作業を行います。 ロックの期限が切れる前にすべてのアクションを終了します。

  • 通常よりも寛容な再試行ロジックを使用すると、補正トランザクションをトリガーするエラーを最小限に抑えることができます。 最終的整合性を実装する操作内のステップが失敗した場合は、エラーを一時的な例外として処理し、ステップを繰り返してみます。 ステップが繰り返し失敗するか回復できない場合にのみ、操作を停止して補正トランザクションを開始します。

  • 補正トランザクションを実装すると、最終的整合性を実装するときに直面するものと同じ課題が多く発生します。 詳細については、「データ整合性入門」の「最終的整合性を実装するための考慮事項」セクションを参照してください。

このパターンを使用する状況

このパターンは、失敗した場合は元に戻す必要がある操作に対してのみ使用します。 可能であれば、補正トランザクションを必要とする複雑さを持たないようにソリューションを設計します。

ワークロード設計

設計者は、Azure Well-Architected Framework の柱で説明されている目標と原則に対処するために、ワークロードの設計でどのように補償トランザクションパターンを使用できるかを評価する必要があります。 次に例を示します。

重要な要素 このパターンが柱の目標をサポートする方法
信頼性設計の決定により、ワークロードが誤動作に対して復元力を持ち、障害発生後も完全に機能する状態に回復することができます。 補償アクションは、データの変更を直接ロールバックしたり、トランザクションのロックを解除したり、ネイティブシステムの動作を実行したりすることで、重要なワークロードパスでの誤動作に対処します。

- RE:02 クリティカルフロー
- RE:09 災害復旧

設計決定と同様に、このパターンで導入される可能性のある他の柱の目標とのトレードオフを考慮してください。

顧客が旅行の Web サイトを使用して旅行プランを予約します。 旅行プランには、一連のフライトとホテルが含まれている可能性があります。 シアトルからロンドン、さらにパリへと旅行する顧客は、旅行プランを作成するときに次のステップを実行すると考えられます。

  1. シアトルからロンドンへのフライト F1 の座席を予約する。
  2. ロンドンからパリへのフライト F2 の座席を予約する。
  3. パリからシアトルへの F3 便の座席を予約する。
  4. ロンドンのホテル H1 の部屋を予約する。
  5. パリのホテル H2 の部屋を予約する。

これらのステップは、最終的に整合性がある操作を構成しますが、各ステップは独立したアクションです。 システムでは、これらのステップを実行するだけでなく、各ステップを元に戻すためのカウンター操作も記録する必要があります。 この情報は、顧客が旅行プランをキャンセルした場合に必要です。 カウンター操作を実行するために必要なステップを補正トランザクションとして実行できます。

補正トランザクションのステップは、元のステップの正反対ではない場合があります。 また、補正トランザクションの各ステップのロジックでは、ビジネス固有のルールを考慮する必要があります。 たとえば、フライト予約をキャンセルしても、顧客が払い戻しを全額受け取れない場合があります。

次の図は、旅行プランを予約するための長期間のトランザクション内のステップを示しています。 トランザクションを元に戻す補正トランザクションのステップも確認できます。

旅行プランを作成するためのステップを示す図。旅行プランを取り消す補正トランザクションのステップも示されています。

注意

各ステップに対する補正ロジックの設計方法によっては、補正トランザクション内のステップを並列で実行できる場合があります。

多くのビジネス ソリューションでは、1 つのステップの失敗によって、補正トランザクションを使用したシステムのロールバックが常に必要になるわけではありません。 たとえば、旅行の Web サイトのシナリオについて考えます。 顧客がフライト F1、F2、F3 を予約していますが、ホテル H1 で部屋を予約できないとします。 フライトをキャンセルする代わりに、同じ市内の別のホテルの部屋を顧客に用意することが望まれます。 この場合でも顧客はキャンセルできます。 その場合、補正トランザクションが実行され、フライト F1、F2、F3 の予約が元に戻されます。 ただし、この決定を行うのは顧客であり、システムではありません。

次の手順

  • Data consistency primer (データ整合性入門)。 最終的整合性モデルを実装する操作を元に戻すには、補正トランザクション パターンがよく使用されます。 この入門では、最終的整合性の利点とトレードオフについて説明します。
  • べき等性のパターン。 補正トランザクションでは、べき等コマンドを使用することをお勧めします。 このブログ記事では、べき等性を実装するときに考慮すべき要因について説明します。
  • Scheduler Agent Supervisor パターン。 この記事では、分散型サービスとリソースを使用するビジネス操作を実行する、回復力のあるシステムを実装する方法について説明します。 これらのシステムでは、補正トランザクションを使用して、操作によって実行した作業を元に戻す必要が生じる場合があります。
  • 再試行パターン。 補正トランザクションは、計算負荷が高くなる可能性があります。 再試行パターンを使用して、失敗した操作を再試行する有効なポリシーを実装することで、それらの使用を最小限に抑えることができます。
  • Saga 分散トランザクション パターン。 この記事では、Saga パターンを使用して、分散トランザクション シナリオでマイクロサービス間のデータ整合性を管理する方法について説明します。 Saga パターンでは、補正トランザクションを使用して障害復旧を行います。
  • パイプとフィルターのパターン。 この記事では、パイプとフィルター パターンについて説明します。これを使用すると、複雑な処理タスクを一連の再利用可能な要素に分解できます。 分散トランザクションを実装する代わりの方法として、パイプとフィルターのパターンを補正トランザクション パターンと一緒に使用できます。
  • 自己復旧の設計。 このガイドでは、自己復旧アプリケーションの設計方法について説明します。 補正トランザクションは、自己復旧アプローチの一環として使用できます。