11

我是 Azure 服务总线的新手,我正在尝试建立用于排队消息的事务策略。由于 SQL Azure 不支持 MSDTC,因此对于分布式 TransactionScope,我无法使用它。所以,我有一个可以手动处理我的数据库事务的工作单元。

问题是我只能找到使用 TransactionScope 来处理数据库和 Azure 服务总线操作的人。有没有其他神奇的方法可以在不使用 TransactionScope 的情况下在 Service Bus 上实现事务?

谢谢。

4

2 回答 2

10

如果您将使用云托管或 Azure 服务总线之类的服务,您应该开始考虑放弃两阶段提交 (2PC) 或分布式事务 (DTC)。

相反,请谨慎使用每个资源的事务(即 SQL 命令的事务或服务总线操作的事务)。并避免跨越该资源边界的事务。

然后,您可以使用可靠的消息传递和模式(如 saga 等)将这些资源/组件操作结合在一起,以进行工作流管理和错误补偿。并从那里向外扩展。

由于各种原因,云中的 2PC 很难(但并非不可能,您仍然可以使用 IaaS)。

由 DTC 实现的 2PC 有效地依赖于协调器及其日志以及与协调器的连接,以实现非常高的可用性。它还取决于各方以权宜之计的方式合作取得积极成果。为此,您需要在故障转移群集中运行 DTC,因为它是整个系统的致命弱点,任何事务都依赖于 DTC 清除它。

我将在这里引用一个很好的例子,说明如何将 2PC 交易视为一系列消息/动作和补偿

2PC 交易的典型例子是银行账户转账。您借记一个帐户并贷记另一个帐户。

这两个操作需要一起成功或失败,否则你要么创造要么摧毁金钱(顺便说一句,这是非法的)。这就是非常常用来说明 2PC 事务的示例。

问题是——这根本不是它真正的工作方式。从一个银行账户向另一个银行账户取钱是一件相当复杂的事情,涉及大量其他账户。更重要的是,这不是一个同步失败/成功的场景。

相反,会计原则适用(惊喜!)。当发起转账时,比方说在网上银行中,转账以消息的形式记录以提交到会计系统,借记在账户中被记录为影响显示余额的“待处理”交易。

从用户的角度来看,交易已经“完成”,但实际上还没有发生任何事情。最终,会计系统将收到消息并开始执行转账,这通常会导致一系列操作,其中许多会产生进一步的消息,包括记入清算账户并通知另一家银行转账。

这里的原则是所有的进步都是向前的。如果某项操作由于某种技术原因无法运行,则可以在技术原因解决后重试。

如果由于业务原因操作失败,则可以中止操作——但不是通过取消以前的工作,而是通过与以前的工作相反的方式。如果一个帐户被记入贷方,则该贷项将被取消,并借记相同金额。

对于某些类型的失败交易,“反向”操作可能不是完全对称的,但可能会导致额外的操作,例如征收罚款。

事实上,在会计中,销毁任何工作都是非法的——“删除”和“更新”是入狱的好方法。

于 2015-01-14T01:21:40.583 回答
0

您可以使用事务范围。它工作得很好。即使您已经发送了一条消息,但是其他一些事情(数据库更新)失败了,那么该消息也不会发布到队列中。

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

于 2020-11-24T10:52:43.150 回答