Azure服务总线和事务

11

我刚接触Azure Service Bus,正在尝试为队列消息建立事务策略。由于SQL Azure不支持MSDTC,因此不能使用分布式TransactionScope。所以,我有一个可以手动处理数据库事务的工作单元。

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

谢谢。


你考虑过使用Sagas吗? - Peter Ritchie
如果您想在云环境中模拟事务,则需要考虑很多因素。这个视频概述了大部分内容:https://particular.net/videos/messaging-without-dtc。这里是其中一种实现方式:https://docs.particular.net/nservicebus/outbox/。 - Kyle Baley
2个回答

11

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

相反,仔细使用每个资源的事务(即 SQL 命令的事务或 Service Bus 操作的事务)。并避免跨越该资源边界的事务。

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

2PC 在云中很难处理 出于各种原因(但不是不可能,您仍然可以使用 IaaS)。

由 DTC 实现的 2PC 实际上取决于协调器及其日志和与协调器的连接非常高度可用。它还依赖于所有参与方积极合作以获得迅速的积极结果。为此,您需要在故障转移群集中运行 DTC,因为它是整个系统的致命弱点,任何事务都取决于 DTC 是否清除它。

我将在这里quote举一个很好的例子,说明如何将2PC事务视为一系列消息/操作和补偿。

2PC事务的典型案例是银行账户转账。你从一个账户借钱,向另一个账户还钱。这两个操作需要同时成功或同时失败,否则你要么创造或销毁资金(顺便说一下,这是非法的)。所以这是很常用的用来说明2PC事务的例子。但问题在于,实际上它并不是这样工作的。把钱从一个银行账户转到另一个银行账户是一个相当复杂的过程,涉及到许多其他账户。更重要的是,这不是同步的“一起失败/一起成功”的情况。相反,会应用会计原则(惊喜!)。当转账被启动,比如在线银行操作时,转账会被记录为提交到会计系统的消息,并且借方会被记录在账户中作为影响显示余额的“待处理”交易。从用户的角度来看,交易已经完成了,但实际上还没有发生任何事情。最终,会计系统会收到消息并开始执行转账,这通常会引起一系列操作,其中许多操作都会产生进一步的消息,包括预定结算账户和通知另一家银行进行转账。这里的原则是所有的进展都是向前的。如果某个操作由于技术原因不起作用,一旦技术原因得到解决,就可以重试。如果操作由于业务原因失败,操作可以被中止,但不能通过抵消以前的工作来实现,而是通过做与以前工作相反的事情来取消以前的工作。如果一个账户被贷款,那么同样金额的贷款将被借记撤销。对于某些类型的失败交易,“相反”操作可能不是完全对称的,但可能会导致额外的行动,比如征收罚款。实际上,在会计学中,任何工作的删除都是非法的,“删除”和“更新”是进入监狱的好方法。

1
您可以使用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文档,您必须使用标准定价而不是基本

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接