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

NserviceBus with Azure Service Bus - how to save domain data transactionally

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

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

三个想法:

  1. 使整个交易的一方或另一方幂等,先做另一方,如果通过try/retry,直到另一方通过。幂等性意味着你可以多次重做一个特定的事务,并且效果将与你重做一次一样。所以,不断重试,直到它通过。这就是我的服务总线和 DocumentDB 系统的设计方式。

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

  3. 由于这两个系统是独立的,我能想到的唯一其他方法就是补偿操作。例如,您可以尝试 DocumentDB 端。如果这涉及多个文档或读取后写入相同的文档,请在存储过程中执行此操作,这将为其提供 ACID 事务保证。一定要以一种你可以逆转它的方式来组合交易(补偿它)。如果 DocumentDB 操作没有失败,则尝试服务总线操作。如果失败,则在 DocumentDB 上执行补偿事务。

请注意,第三个选项仍然不是完美的解决方案。如果在您尝试服务总线操作期间,在 DocumentDB 端完成了某些操作,导致无法以一致的方式逆转该方面,您现在将处于不一致状态。如果它以无法忽略的方式发生,请确保系统会发出红旗。由您来为您的系统建模并确定它的罕见程度。请记住,生活在极其罕见的事件中是可以的。想一想 GUID 是如何组成的。仍有可能发生碰撞。这种情况非常罕见,您无需担心。

即使它不 "exceedingly" 罕见,您可能仍想这样做,具体取决于不一致的罕见程度和破坏性程度。比方说,服务总线操作失败的几率为万分之一,补偿事务失败的几率为万分之一。那么两者同时发生的几率是一亿分之一。如果你一个月做 1,000,000 次这样的事情,那么第一个发生的中位数将花费你 50 个月的时间,而且它们之间的间隔大约为 100 个月。然后确定那有多糟糕。如果修复其中一个问题需要花费 10,000 美元(向客户支付违反 SLA 的费用 + 人工修复),您能否负担得起每 100 个月一次的费用?

我可能会进一步分析并创建一个 Monty Carlo 模拟来测试模型中的不确定性。您可能不知道它是万分之一的几率,您可能会说,我有 70% 的把握或 90% 的把握它在 1/1,000 到 1/100,000 之间。 Monte Carlo 模拟将允许您在该范围内 "roll the dice" 并生成第一年成本的概率曲线。输出会这样说,“第一年至少花费 100,000 的可能性为 10%;第一年至少花费 10,000 的可能性为 40%,而第一年的可能性为 90%第一年我们至少要花费 1,000 美元。

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