如果发生任何失败,Saga Pattern 是否能够帮助扭转支出?

Does Saga Pattern able to help to reverse Payouts incase if any Failure occurs?

我对 Saga 模式还很陌生。我了解到,在 Saga 的帮助下,如果发生任何故障,我们可以扭转局面。

无论我看到的例子是什么,它们大多是 Orders Service -> Payment Service -> Other Service,在 Payment service 中,funds happen从客户到商户,万一如果其他服务发生任何故障,此支付交易可以撤销,因为这里的资金从商户流向客户(在逆向失败过程中)

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

付款服务中,资金发生在商家到客户之间

万一客户服务出现任何故障,我们能否使用 Saga 撤销付款交易? (即,将资金从客户转回商家,以防出现任何故障)

以上是否可以使用 Saga?希望我的查询很清楚。如果有人能在上面帮助我,我会很高兴。

saga 模式允许您协调多个操作,以防万一其中一个步骤失败,它允许您协调步骤以反转到目前为止已完成的操作,因此您可以看到它在没有实际交易的情况下完成所有步骤 transactional

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

这种情况下,你能做的就是将不可逆转的操作留到最后。例如,将客户钱包中的钱打折(这是对您拥有的数据库的操作),然后进行实际支付。如果付款失败,saga 将允许您从客户的钱包中撤消扣除,因此不会造成 "damage"。


更新: 根据评论

添加的额外信息

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

另外请注意,saga 执行的步骤可能会出现暂时性故障或 unrecoverable/permanent 故障。瞬态故障可以重试,而且很可能会成功。永久性失败不会通过重试成功。

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

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

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