10

次のようなメソッドがあると想像してください。

public void PlaceOrder(Order order)
{
     this.SaveOrderToDataBase(order);
     this.bus.Publish(new OrderPlaced(Order));    
}

注文がデータベースに保存された後、イベントがメッセージ キューイング システムにパブリッシュされ、同じマシンまたは別のマシン上の他のサブシステムがそれを処理できるようになります。

しかし、this.bus.Publish(new OrderPlaced(Order))呼び出しが失敗した場合はどうなりますか? または、注文をデータベースに保存した直後にマシンがクラッシュしますか? イベントは発行されず、他のサブシステムはそれを処理できません。これは受け入れがたい。これが発生した場合、イベントが最終的に公開されるようにする必要があります。

使用できる受け入れ可能な戦略は何ですか? どれが最高ですか?

注: 分散トランザクションを使用したくありません。

編集:

Paul Sasik は非常に近く、100% 達成できると思います。これは私が考えたことです:

最初に、次のようにデータベースにテーブル Events を作成します。

CREATE TABLE Events (EventId int PRIMARY KEY)

int の代わりに GUID を使用したい場合や、シーケンスまたは ID を使用したい場合があります。

次に、次の擬似コードを実行します。

open transaction
save order and event via A SINGLE transaction
in case of failure, report error and return
place order in message queue
in case of failure, report error, roll back transaction and return
commit transaction

すべてのイベントに EventId を含める必要があります。イベント サブスクライバーがイベントを受信すると、最初にデータベース内の EventId の存在を確認します。

このようにして、99.999% だけでなく、100% の信頼性が得られます。

4

2 に答える 2

2

this.bus.Publishのデータベース トランザクションの呼び出し部分を作成できますthis.SaveOrderToDataBase。これはthis.SaveOrderToDataBase、トランザクション スコープで実行され、db 呼び出しが失敗した場合は mq を呼び出さず、mq 呼び出しが失敗した場合は db トランザクションをロールバックして、両方のシステムを一貫した状態のままにすることを意味します。両方の呼び出しが成功した場合、db トランザクションをコミットします。

擬似コード:

open transaction
save order via transaction
in case of failure, report error and return
place order in message queue
in case of failure, report error, roll back transaction and return
commit transaction

特定の db テクノロジーについては言及していないので、トランザクションに関する wiki 記事へのリンクを次に示します。トランザクションに慣れていない場合でも、開始するのに適した場所です。良いニュースもあります。実装は難しくありません。

于 2015-06-11T12:41:36.730 に答える