我是Azure Service Bus的新手,我正在尝试为排队邮件建立事务策略。由于SQL Azure不支持MSDTC,因此使用分布式TransactionScope,我无法使用它。所以,我有一个可以手动处理我的数据库事务的工作单元。
问题是我只能找到使用TransactionScope来处理数据库和Azure Service Bus操作的人。有没有其他神奇的方法可以在不使用TransactionScope的情况下在Service Bus上实现事务?
感谢。
答案 0 :(得分:3)
如果您将使用云托管或服务如天蓝色服务总线,您应该开始考虑放弃两阶段提交(2PC)或分布式事务(DTC)。
相反,请仔细使用每资源事务(即SQL命令的事务或服务总线操作的事务)。并避免跨越该资源边界的交易。
然后,您可以使用可靠的消息传递和模式(如sagas等)将这些资源/组件操作组合在一起,以进行工作流管理和错误补偿。并从那里扩展。
云中的2PC很难all sorts of reasons(但并非不可能,您仍然可以使用IaaS)。
由DTC实现的2PC实际上取决于协调器及其日志和与协调器的连接是否具有高可用性。它还取决于所有各方以权宜之计的方式合作取得积极成果。为此,您需要在故障转移群集中运行DTC,因为它是整个系统的致命弱点,任何事务都依赖于DTC清除它。我quote这里有一个很好的例子,说明如何将2PC交易视为一系列消息/动作和补偿
2PC交易的典型示例是银行账户转账。您借记一个帐户并为另一个帐户贷记。
这两个操作需要一起成功或失败,因为否则你要么创造或破坏金钱(顺便说一句,这是非法的)。这就是通常用来说明2PC交易的例子。
问题在于 - 根本不是它真正起作用的方式。从一个银行账户获取资金到另一个银行账户是一件相当复杂的事情,触及了大量其他账户。更重要的是,它不是一个同步失败/一起成功的场景。
相反,会计原则适用(惊喜!)。当启动转账时,假设在网上银行中,转账以消息的形式记录,以便提交到会计系统,借方在账户中记录为影响显示余额的“待处理”交易。
从用户的角度来看,交易是“完成的”,但实际上并没有发生任何事情。最终,会计系统将获得消息并开始执行转移,这通常会导致一系列操作,其中许多操作会产生进一步的消息,包括预订到清算帐户并通知另一家银行的转帐。
这里的原则是所有进步都是前进的。如果由于某些技术原因操作无效,则可在技术原因得到解决后重试。
如果由于商业原因操作失败,则操作可以中止 - 但不能通过消除以前的工作,而是通过执行与之前工作相反的操作。如果一个帐户被记入贷方,该贷记将被取消相同金额的借方。
对于某些类型的失败交易,“逆向”操作可能不是完全对称的,但可能会导致额外的操作,例如征收罚款。
事实上,在会计方面,消灭任何工作都是非法的 - “删除”和“更新”是最终入狱的好方法。
答案 1 :(得分:0)
您可以使用TransactionScope。效果很好。即使您已经发送了一条消息,但是其他(数据库更新)失败了,该消息也不会发布到队列中。
using var scope = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled);
try
{
var messageBody = "This is my message";
var message = new Message(Encoding.UTF8.GetBytes(messageBody));
await _queueClient.SendAsync(message);
await _myOtherService.FailPotentially(); // if this method fails then message will ne rolled back
scope.Complete();
}
catch (Exception exception)
{
scope.Dispose();
_logger.LogError(" ... ", exception);
throw;
}
根据ServiceBus documentation,您必须使用standard
的{{1}}定价方式