Transactions N服务总线与Azure服务总线-如何以事务方式保存域数据

Transactions N服务总线与Azure服务总线-如何以事务方式保存域数据,transactions,nservicebus,azureservicebus,azure-cosmosdb,Transactions,Nservicebus,Azureservicebus,Azure Cosmosdb,我想将域事件保存为DocumentDB中的文档,然后将该事件发布到Azure服务总线(ASB)上,供其他服务获取。我希望在一个事务中执行这两个操作,以便在其中一个操作失败时,自动回滚另一个操作 ASB为处理程序中的传入和传出(下游)消息提供事务支持,即,如果处理程序失败,这些消息将不会发送,并且处理程序中接收的原始消息不会从总线中删除。但是,保存在同一个处理程序中的任何数据,比如在我的例子中,将事件存储在DocumentDB中,会怎么样呢?如何将其包括在该交易中?三个想法: 使整个事务的一方或另

我想将域事件保存为DocumentDB中的文档,然后将该事件发布到Azure服务总线(ASB)上,供其他服务获取。我希望在一个事务中执行这两个操作,以便在其中一个操作失败时,自动回滚另一个操作

ASB为处理程序中的传入和传出(下游)消息提供事务支持,即,如果处理程序失败,这些消息将不会发送,并且处理程序中接收的原始消息不会从总线中删除。但是,保存在同一个处理程序中的任何数据,比如在我的例子中,将事件存储在DocumentDB中,会怎么样呢?如何将其包括在该交易中?

三个想法:

  • 使整个事务的一方或另一方幂等,首先执行另一方,如果通过,则尝试/重试,直到另一方通过。幂等性意味着您可以多次重做特定事务,其效果将与您执行一次相同。所以,继续重试,直到它通过。这就是我的服务总线和DocumentDB系统的设计方式

  • 从这些类型操作的设计中删除服务总线,并使用DocumentDB作为服务总线。然后确保在对存储过程的一次调用中执行所有希望被视为一个事务的操作,该调用将为存储过程提供ACID全通或全失败事务保证。您可能仍然可以使用服务总线进行其他操作,但不能用于这些操作

  • 由于这两个系统是独立的,我唯一能想到的另一种方法就是采取补偿措施。例如,您可以尝试DocumentDB端。如果这涉及到多个文档,或者读取后再写入同一个文档,请在一个存储过程中执行,该存储过程将为其提供ACID事务保证。确保以一种可以反转(补偿)事务的方式编写事务。如果DocumentDB操作没有失败,请尝试服务总线操作。如果失败,则在DocumentDB上执行补偿事务

  • 注意,第三个选项仍然不是一个完美的解决方案。如果在您尝试服务总线操作的过程中,DocumentDB端执行了某些操作,使得无法以一致的方式反转该方面,那么您现在将处于不一致状态。如果以一种不可忽视的方式发生,请确保系统会抛出一个红旗。这取决于您对您的系统进行建模,并确定这种情况有多罕见。记住,生活在极其罕见的事件中是可以的。想想guid是如何组成的。仍然有可能发生碰撞。它是如此罕见,以至于你不需要担心它

    即使它不是“非常”罕见,您可能仍然希望这样做,这取决于不一致性的罕见程度和破坏程度。比方说,服务总线操作失败的几率是万分之一,补偿事务失败的几率是万分之一。那么这两种情况都发生的几率是1/100000000。如果你一个月做1000000次,第一次发生的平均时间是50个月,大约相隔100个月。然后确定这有多糟糕。如果修复其中一个需要花费10000美元(向客户支付违反SLA的费用+人工修复费用),您是否能够每100个月支付一次该费用

    我可能会进一步分析,创建一个Monty Carlo模拟来测试模型中的不确定性。你可能不知道这是万分之一的机会,你可能会说,我70%肯定或者90%肯定这是在千分之一到十万分之一之间。蒙特卡罗模拟将允许您在该范围内“掷骰子”,并生成第一年成本的概率曲线。输出会这样说,“有10%的可能性,它将在第一年花费我们至少100000美元;有40%的可能性,它将在第一年花费我们至少10000美元,有90%的可能性,它将在第一年花费我们至少1000美元

    大多数工程师不习惯于这样的概率决策,但这正是我的许多写作、演讲和咨询的内容,我已经习惯于帮助工程组织以这种方式做出决策,主要是在如何建模负荷以及如何预测某个特定范围何时完成(但在OCCA上)ion我做的模型和上面描述的一样。结果让团队对他们的决定有了更高的信心