2013-07-23 11 views
14

状況を想像してみて:データベーストランザクションでのRabbitMQの統合

var txn = new DatabaseTransaction(); 

var entry = txn.Database.Load<Entry>(id); 
entry.Token = "123"; 
txn.Database.Update(entry); 

PublishRabbitMqMessage(new EntryUpdatedMessage { ID = entry.ID }); 

// A bit more of processing 

txn.Commit(); 

EntryUpdatedMessageの消費者が潜在的に前取引txnがコミットされるため、更新を確認することができません。このメッセージを得ることができます。

RabbitMQはトランザクションを単独でサポートしていますが、実際には使用することはできません。なぜなら、公開ごとに新しいIModelを作成し、スレッドごとのモデルを作成するのは実際には面倒です(ASP.NET Webアプリケーション)。

DBトランザクションがコミットされたときに公開される予定のメッセージのリストがあると思っていましたが、それは本当にうっとうしい解決策です。

これを正しく処理する方法は何ですか?

答えて

28

RabbitMQでは、トランザクションではなくパブリッシャーの確認を使用することをお勧めします。トランザクションはうまく動作しません。

いずれの場合でも、トランザクションは通常、サービス指向アーキテクチャではうまく機能しません。後で失敗が再試行され、重複しないメッセージが無視される「最終的に一貫性のある」アプローチを採用する方が良いでしょう。

私の例では、データベースの更新を行い、メッセージを公開する前にコミットします。パブリッシャーが返信を確認すると、メッセージが送信されたことを示すためにデータベースレコードのフィールドを更新します。その後、スイーパープロセスを後で実行し、未送信のメッセージをチェックし、途中で送信することができます。メッセージが通過したにもかかわらず何らかの理由で確認または後続のデータベース書込みに失敗した場合は、重複したメッセージが表示されます。しかし、それは重要ではありません。あなたのメッセージが冪等であるように設計したからです。