发送后NserviceBus回滚

时间:2017-12-08 09:43:28

标签: nservicebus

嗨,我有这段代码

 SendMessageToMyQueue();
UpdateStatusInDbThatMessageWasSent();

有时在状态更新之前处理消息,我想避免。

我的问题是,如果我用这样的事务包装那两行:

using(var tr = new TransactionScope())
{
  SendMessageToMyQueue();
UpdateStatusInDbThatMessageWasSent();
tr.Compleate();
}

将保证MyQueue创建一个锁,并且在UpdateStatusInDbThatMessageWasSent更新状态之前不会释放此锁定?

如果我添加带有回滚的try catch并且更新状态失败,该消息是否会从MyQueue中删除?

1 个答案:

答案 0 :(得分:1)

没有锁定队列这样的东西。但是,如果满足以下条件,则将以事务方式处理该消息。通过事务方式,我的意思是如果抛出未处理的异常,消息将返回到队列。实现这一目标的条件是:

  • 您的数据库可以登记并参与分布式事务。不是每个数据库都有。某些文档数据库没有(对于MongoDB)或粗略(对于RavenDB)支持DTC。

  • 您的传输还支持分布式事务。如果您使用代理类型传输,SQL Server传输是您最好的选择,并且在总线类型传输上MSMQ是一个不错的选择。 Azure ServiceBus或RabbitMQ等传输的事务支持非常有限,不支持分布式事务。

  • 您需要运行已配置并运行的分布式事务处理协调器服务。

另外两件事需要注意:

  • 如果您使用缺乏DTC支持的运输怎么办?大多数情况下,如果您可以将系统设计为idempotent,那么您会感觉更好。 NServiceBus的Outbox功能允许您在一定程度上模拟DTC。

  • 当从队列中挑选消息,处理消息并由于异常而返回到队列时,它可能最终位于队列中的不同位置。在设计基于消息的架构时,您需要design for messages arriving out of order

综上所述,exactly-once delivery guarantees始终是一个热门话题并且存在争议。