Service Bus のトランザクション処理の概要

この記事では、Microsoft Azure Service Bus のトランザクション機能について説明します。 ディスカッションの多くはトランザクション サンプルに示されています。 この記事はトランザクション処理の概要と Service Bus の "経由送信" 機能に限定されていますが、アトミック トランザクションのサンプルの範囲はこれよりも広く複雑です。

Note

  • Service Bus の Basic レベルでは、トランザクションはサポートされません。 Standard と Premium レベルでは、トランザクションはサポートされます。 これらのレベルの違いについては、「Service Bus の価格」を参照してください。
  • トランザクションでの管理操作とメッセージング操作の混在はサポートされていません。
  • JavaScript SDK はトランザクションをサポートしていません。

Service Bus でのトランザクション

トランザクションにより、2 つ以上の操作が 1 つの実行スコープにグループ化されます。 性質上、このようなトランザクションによって、操作の特定のグループに属する操作がすべて成功するか、すべて失敗するかのいずれかになる必要があります。 この点において、トランザクションは 1 つの単位として動作します。このことは、多くの場合 "原子性 "と呼ばれます。

Service Bus はトランザクション メッセージ ブローカーであり、そのメッセージ ストアに対するすべての内部操作のトランザクション整合性を確保します。 配信不能キューへのメッセージの移動や、エンティティ間のメッセージの自動転送などの、すべての Service Bus 内のメッセージ転送は、トランザクショナルです。 そのため、Service Bus がメッセージを受け入れる場合、メッセージは既に格納されて、シーケンス番号のラベルが付けられています。 それ以降、Service Bus 内のメッセージの転送はエンティティ間で連動する操作となり、メッセージが失われる (ソースが成功し、ターゲットが失敗する) ことも、重複する (ソースが失敗し、ターゲットが成功する) こともありません。

Service Bus は、トランザクションのスコープ内の単一メッセージング エンティティ (キュー、トピック、サブスクリプション) に対するグループ化操作をサポートしています。 たとえば、トランザクション スコープ内から 1 つのキューにいくつかのメッセージを送信できます。また、トランザクションが正常に完了したときにのみ、メッセージがキューのログにコミットされます。

トランザクション スコープ内での操作

トランザクション スコープ内で実行できる操作は次のとおりです。

  • 送信
  • 完了
  • Abandon
  • 配信不能
  • 延期
  • ロックの更新

一部の受信ループ内、またはコールバックで、peek-lock モードを使用してアプリケーションがメッセージを取得した後にのみ、メッセージを処理するためのトランザクション スコープを開くことを前提としているため、受信操作は含まれません。

その後、メッセージの処理 (完了、破棄、配信不能、延期) がトランザクションのスコープ内で発生します。この処理の発生は、トランザクションの全体的な結果に依存します。

重要

操作がトランザクション スコープ内にあるときの例外の場合、Azure Service Bus によって操作は再試行されません。

トランザクション スコープに登録しない操作

データベースや Cosmos DB などの他のサービスを呼び出すメッセージ処理コードでは、それらのダウンストリーム リソースが同じトランザクション スコープに自動的に登録されないことに注意してください。 これらのシナリオの処理方法について詳しくは、べき等メッセージ処理についてのガイドラインに関する記事をご覧ください。

転送および "経由送信"

キューまたはトピックからプロセッサ、そこから別のキューまたはトピックへのデータのトランザクションの移行を有効にするために、Service Bus では "転送" がサポートされています。 転送操作では、送信者がまず "転送キューまたはトピック" にメッセージを送信すると、転送キューまたはトピックが、自動転送機能で使用されているものと同じ堅牢な転送実装を使用して、すぐに目的の送信先キューまたはトピックにメッセージを移動します。 メッセージは、転送キューまたはトピックのコンシューマーに表示されるようになる方法で、転送キューまたはトピックのログにコミットされることはありません。

転送キューまたはトピック自体が送信者の入力メッセージの送信元である場合は、このトランザクションの機能の能力が明らかになります。 言い換えれば、Service Bus では、転送キューまたはトピックを "経由" してメッセージを送信先キューまたはトピックに転送できる一方で、すべてを 1 つのアトミック操作で、入力メッセージに対する完了 (または延期や配信不能) 操作を実行します。

トピック サブスクリプションから受信した後、同じトランザクション内のキューまたはトピックに送信する必要がある場合は、転送エンティティがトピックである必要があります。 このシナリオでは、トピックでトランザクション スコープを開始し、トランザクション スコープ内のサブスクリプションから受信し、転送トピックを介してキューまたはトピックの送信先に送信します。

Note

メッセージがトランザクションのスコープ内の転送キュー経由で送信される場合、TransactionPartitionKeyPartitionKey と機能的に同等です。 これにより、メッセージは、転送される順序でまとめられます。

コードでの確認

このような転送を設定するには、転送キューを経由して送信先キューを対象とするメッセージの送信者を作成します。 同じキューからメッセージをプルする受信者も必要です。 次に例を示します。

その後、単純なトランザクションで、次の例のように、これらの要素を使用します。 完全な例については、GitHub 上のソース コードを参照してください。

var options = new ServiceBusClientOptions { EnableCrossEntityTransactions = true };
await using var client = new ServiceBusClient(connectionString, options);

ServiceBusReceiver receiverA = client.CreateReceiver("queueA");
ServiceBusSender senderB = client.CreateSender("queueB");

ServiceBusReceivedMessage receivedMessage = await receiverA.ReceiveMessageAsync();

using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
    await receiverA.CompleteMessageAsync(receivedMessage);
    await senderB.SendMessageAsync(new ServiceBusMessage());
    ts.Complete();
}

EnableCrossEntityTransactionsプロパティの詳細については、次のリファレンス ServiceBusClientBuilder.enableCrossEntityTransactions メソッドを参照してください。

タイムアウト

トランザクションは 2 分後にタイムアウトになります。 トランザクションの最初の操作が開始されると、トランザクション タイマーが開始されます。

次のステップ

Service Bus キューの詳細については、次の記事を参照してください。