如何模拟账户余额检查? (最终一致性/事件驱动架构是不是可能?)

Posted

技术标签:

【中文标题】如何模拟账户余额检查? (最终一致性/事件驱动架构是不是可能?)【英文标题】:How to model account balance check? (Is it possible with eventual consistency / event driven architecture?)如何模拟账户余额检查? (最终一致性/事件驱动架构是否可能?) 【发布时间】:2021-12-04 21:42:57 【问题描述】:

如果有 2 个有界上下文:SpendingAccount management,如何防止用户花费不超过余额?

我理解我们有单个产品的Order > Payment > Shipment 序列的情况,但这里更像Order > Balance Check > Shipment,我不明白如何在其他有界上下文中检查余额并确保用户永远不会花费更多比他有。

这种情况甚至可以通过最终的一致性来解决吗?我希望它具有最终的一致性。如果不是,safe 选项是否可以在Spending 有界上下文中保持平衡?

[更新] 我没有提到,我正在考虑事件驱动架构中的解决方案,其中有界上下文仅通过事件交换信息。

【问题讨论】:

【参考方案1】:

在您的情况下,余额检查的最终一致性是不合适的。

要求:在我们知道客户可以付款之前不要发货。

因此,您有一个明确的业务要求,即发货流程必须等待来自帐户余额检查流程的响应。如果余额检查服务停止,则无法继续发货。

在其他业务场景中,您可以继续处理流程的一部分,让另一部分在服务之间通过进程外消息传递实现最终一致性。在您的情况下,您不能对流程的检查余额部分执行此操作。

更复杂的是,您的过程将是:

订单 > 检查余额 > 发货 > 扣款。

您不希望在发货之前扣除资金,以防由于某种原因发货失败,但您绝对不想在检查余额之前发货。

为此,我将介绍“专用”或“预留资金”的概念。

因此,您的“支出”上下文将向“客户经理”上下文发送“储备金”请求并等待响应。该响应可以包括“预留资金”的相关 ID。您的账户管理服务需要了解“实际余额”和“预留资金”的概念才能计算“可用余额”。

发货完成后,您可以向账户管理发送“确认”并引用相关 ID,以便账户管理可以调整“实际余额”并删除“预留资金”。在我看来,这一步可以最终保持一致。

【讨论】:

要求:在我们知道客户可以付款之前不要发货 - 特别感谢这句话!这让人大开眼界。到目前为止,我一直在想在我们知道他可以付款之前不要让客户订购,但你的配方要好得多。其他一切都是自然而然地衍生出来的。 另外,我想你会在Spending BC 中保留一些Order.Status 字段,这些字段会随着其他 BC 的工作而更新,对吧? 如果您需要它来执行您的域逻辑,那么可以。但是,不要仅仅因为你认为它可能有用就创建一个。在需要时创建它。 YAGNI 是一个强大的工具。 好吧,即使它不是用于域逻辑,而是用于纯 UI,以让用户了解订单的状态(除了为每个事件/步骤发送电子邮件)。 /btw,这些实际上是题外话,所以标记为答案。谢谢! 我在读回自己的最后一条评论后删除了它。维护读取模型的提要状态很好。很抱歉造成混乱。

以上是关于如何模拟账户余额检查? (最终一致性/事件驱动架构是不是可能?)的主要内容,如果未能解决你的问题,请参考以下文章

领域驱动设计系列贫血模型和充血模型

多并发时支付如何保持账户余额的一致性?

EXCEL函数计算不同银行账户余额

JAVA多线程用实现Runnable接口的方式创建线程

Python程序练习3--模拟购物车

卡余额有限的 PayPal 沙盒账户