如果发生任何故障,Saga 模式是否能够帮助逆转支出?

joh*_*ohn 2 design-patterns cqrs event-sourcing saga microservices

我对传奇模式很陌生。我明白了,在Saga的帮助下,如果出现任何故障,我们都可以扭转局面。

无论我见过什么例子,它们大多都是像Orders Service -> Payment Service -> Other Service,在 Payment service 中,资金是从 Customer 到 Merchant 发生的如果其他 Service 发生任何故障,这个支付交易可以是能够逆转,因为这里资金从商家流向客户(在逆转失败过程中)

但是,我的查询是:我有一个像这样的反向场景:付款服务 -> 客户服务

支付服务中,资金从商户流向客户

如果客户服务出现任何故障,我们是否可以使用 Saga 逆转付款交易?(即,将资金从客户转回商家,以防发生任何故障)

以上可以使用Saga吗?希望我的疑问很清楚。如果有人能够在上述方面帮助我,我会很高兴。

Fra*_*lls 5

saga 模式允许您协调许多操作,如果其中一个步骤失败,它允许您协调这些步骤以反转到目前为止已完成的操作,因此您可以通过以下方式查看它:所有步骤transactional均无需实际交易。

但传奇无法改变您所做的每个步骤的性质。向客户收费是一项我们可以逆转的操作,因为我们可以创建补偿操作,例如将资金退还给客户。向客户付款是一项我们无法逆转的操作,因为一旦钱到了客户手中,我们就无法收回。因此,传奇可以帮助您确保所有步骤都已发生或确保什么都没有发生,但它不会让您逆转无法逆转的事情。

这种情况下,你能做的就是把无法逆转的操作留在最后。例如,从客户钱包中打折资金(这是对您拥有的数据库的操作),然后进行实际支付。如果支付失败,传奇将允许您从客户的钱包中撤回扣除的金额,因此不会造成“损害”。


更新:根据评论添加额外信息

Sagas(通常)通过消息传递来实现。传奇是协调器,它并不真正执行实际步骤。相反,它发出命令,以便其他进程执行步骤并接收带有操作结果的消息或事件。

另请注意,saga 执行的步骤可能会出现暂时性故障或不可恢复/永久故障。暂时的失败可以重试,并且很可能会成功。永久失败不会因重试而成功。

考虑到所有这些,我将按如下方式解决问题:

  1. 发送命令来更新数据库并存储正在发生的事务。这会锁定资金,因此即使尚未支付,您也不能发起另一笔支付并最终支付过多的钱。这里的失败可能是暂时的(数据库不可用)或永久性的(没有足够的资金)。您可以重试暂时性故障,直到其正常工作并通知永久性故障。将包含操作结果的消息发送回 saga。
  2. 如果步骤 1 成功,则发送命令执行支付。瞬时故障:外部服务不可用。重试最多 X 次。永久:支付数据无效。如果无法支付,saga 将补偿步骤 1 并释放钱包中的资金。将消息发送回 saga,并包含结果:失败或来自外部 HTTP 服务的响应。
  3. 如果支付失败,则发送命令回滚步骤1。如果成功,则发送命令确认支付并将响应存储在DB中。请注意,更新数据库时不应出现永久性故障。最多,您可能会遇到暂时性故障(数据库不可用),但重试应该能够最终更新数据库。如果多次重试后操作仍无法成功。您需要手动干预并解决问题,因为您无法回滚步骤 2。您应该对流程进行建模,以便此步骤可靠(验证和其他可能导致永久性故障的事情应在步骤 1 或 2 中捕获) 。

我希望这是有道理的。您需要确保涵盖所有场景,并且即使操作失败也可以可靠地发送消息。