8

私が説明しようとしているのは、基本的に 2 つの異なるシステム間の 2 フェーズ コミットの問題であり、その処理方法についてアドバイスを求めています。私たちの Web アプリケーションでは、電子メールの送信など、一部の高価な/サードパーティの操作を帯域外のバックグラウンド ワーカー プロセス (ジョブ インフラストラクチャと呼んでいます) にオフロードします。

たとえば、電子メールを送信するには、データベースに電子メール オブジェクトと電子メール ジョブの両方を作成します。次に、ジョブ モニターがメール ジョブを取得して送信するのを待つ必要があります。ジョブ モニターは基本的に、データベースがアイドル状態のときに数秒ごとにデータベースをポーリングすることによって機能します。

ただし、これにより電子メールの送信に遅延が追加され、ポーリングによるデータベースへの過度の負荷と見なされるものが追加されます。電子メールが作成されたらすぐに電子メール ジョブをキューに入れることができれば、さらに便利です。

ただし、これは現在 2 つの理由で失敗しています。まず、キューは多くの場合、Web 要求よりもはるかに高速です。Web 要求がデータベース トランザクションをコミットする前に電子メールが処理のために取得されるため、電子メールを適切に生成できません。次に、Web 要求が失敗すると、データベース トランザクションがロールバックされます。これは、電子メールが送信されないことを意味します。ただし、すでにキューに入れられている場合は、リクエストの制御下にはありません。

キューとデータベースの間で 2 フェーズ コミットを作成するための適切な戦略はありますか? 参考までに、InnoDB テーブルで RabbitMQ と MySQL を使用しています。私が頭に浮かんだアイデアの 1 つは、データベース トランザクションがコミットされた後に電子メール ジョブをキューに保持することでしたが、それでは電子メールがキューに入れられない可能性が残ります。送信されるべきで送信されなかった電子メールを監視するポーリング プロセスを作成する必要があります。

4

1 に答える 1

1

これは数年遅れていることに気づきました:)しかし、この質問に出くわした他の人のために、これについていくつかの考えを追加したかったのです。

ジョブが DB を取得したときに DB の準備が整っている可能性を高めるために、遅延してメッセージを送信できます。RabbitMQ を使用したことはありませんが、rabbitMQ キューを遅延キューとして使用する例を見つけました。RabbitMQ で遅延キューを作成する方法は? . 遅延は分散処理を処理する決定論的な方法ではないため、電子メールジョブはコメントされていないレコードを処理する必要があります。

とはいえ、デザインを改善する余地があるように感じます。一般に、サービス アーキテクチャでは、サービス間で db テーブルを共有することはお勧めできません。これは、分散トランザクションとスケーリングの問題につながります。私は、RabbitMQ メッセージに、他のサービスとは無関係に電子メールを処理するために必要なすべてのデータが含まれていることを保証しようとします。または、さらにデータが必要な場合は、DB クエリではなく ServiceBus リクエストを介してそのデータをリクエストする必要があります。

于 2014-02-14T20:30:27.240 に答える