我是 Azure 服务总线的新手,我正在尝试建立用于排队消息的事务策略。由于 SQL Azure 不支持 MSDTC,因此对于分布式 TransactionScope,我无法使用它。所以,我有一个可以手动处理我的数据库事务的工作单元。
问题是我只能找到使用 TransactionScope 来处理数据库和 Azure 服务总线操作的人。有没有其他神奇的方法可以在不使用 TransactionScope 的情况下在 Service Bus 上实现事务?
谢谢。
我是 Azure 服务总线的新手,我正在尝试建立用于排队消息的事务策略。由于 SQL Azure 不支持 MSDTC,因此对于分布式 TransactionScope,我无法使用它。所以,我有一个可以手动处理我的数据库事务的工作单元。
问题是我只能找到使用 TransactionScope 来处理数据库和 Azure 服务总线操作的人。有没有其他神奇的方法可以在不使用 TransactionScope 的情况下在 Service Bus 上实现事务?
谢谢。
如果您将使用云托管或 Azure 服务总线之类的服务,您应该开始考虑放弃两阶段提交 (2PC) 或分布式事务 (DTC)。
相反,请谨慎使用每个资源的事务(即 SQL 命令的事务或服务总线操作的事务)。并避免跨越该资源边界的事务。
然后,您可以使用可靠的消息传递和模式(如 saga 等)将这些资源/组件操作结合在一起,以进行工作流管理和错误补偿。并从那里向外扩展。
由于各种原因,云中的 2PC 很难(但并非不可能,您仍然可以使用 IaaS)。
由 DTC 实现的 2PC 有效地依赖于协调器及其日志以及与协调器的连接,以实现非常高的可用性。它还取决于各方以权宜之计的方式合作取得积极成果。为此,您需要在故障转移群集中运行 DTC,因为它是整个系统的致命弱点,任何事务都依赖于 DTC 清除它。
我将在这里引用一个很好的例子,说明如何将 2PC 交易视为一系列消息/动作和补偿
2PC 交易的典型例子是银行账户转账。您借记一个帐户并贷记另一个帐户。
这两个操作需要一起成功或失败,否则你要么创造要么摧毁金钱(顺便说一句,这是非法的)。这就是非常常用来说明 2PC 事务的示例。
问题是——这根本不是它真正的工作方式。从一个银行账户向另一个银行账户取钱是一件相当复杂的事情,涉及大量其他账户。更重要的是,这不是一个同步失败/成功的场景。
相反,会计原则适用(惊喜!)。当发起转账时,比方说在网上银行中,转账以消息的形式记录以提交到会计系统,借记在账户中被记录为影响显示余额的“待处理”交易。
从用户的角度来看,交易已经“完成”,但实际上还没有发生任何事情。最终,会计系统将收到消息并开始执行转账,这通常会导致一系列操作,其中许多会产生进一步的消息,包括记入清算账户并通知另一家银行转账。
这里的原则是所有的进步都是向前的。如果某项操作由于某种技术原因无法运行,则可以在技术原因解决后重试。
如果由于业务原因操作失败,则可以中止操作——但不是通过取消以前的工作,而是通过与以前的工作相反的方式。如果一个帐户被记入贷方,则该贷项将被取消,并借记相同金额。
对于某些类型的失败交易,“反向”操作可能不是完全对称的,但可能会导致额外的操作,例如征收罚款。
事实上,在会计中,销毁任何工作都是非法的——“删除”和“更新”是入狱的好方法。
您可以使用事务范围。它工作得很好。即使您已经发送了一条消息,但是其他一些事情(数据库更新)失败了,那么该消息也不会发布到队列中。
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 文档,您必须使用standard
定价而不是basic