0

我有两个服务名称产品和订单。OrderDb 中的订单表有 price 和 productId 列,用于存储订购的产品价格和产品 ID。订单服务有 3 个副本。

现在,假设订购了一个产品,它的 id 为 80,并且从产品服务触发了一系列顺序更新事件,以针对该特定产品订购服务:

event1:{productId: 80, price: 500}
event2:{productId: 80, price: 600}
event3:{productId: 80, price: 400}
event4:{productId: 80, price: 900}
event5:{productId: 80, price: 100}

所以该产品的最终价格应该是 100,但有时这些事件是按随机顺序处理的,例如

event1:{productId: 80, price: 500}
event2:{productId: 80, price: 600}
event5:{productId: 80, price: 100}
event4:{productId: 80, price: 900}
event3:{productId: 80, price: 400}

由于最后处理事件 3,价格变为 400。

4

2 回答 2

2

这通常取决于您的数据库。我看到你将 NATS 放在标签中,所以我假设你的意思是你有某种工作队列模型,但你可能有一个记录数据库,它有自己的一致性模型。对于想要防止乱序或多次交付的事件流系统,您可以在队列消息中包含更多信息,例如对象版本,或者只是之前的价格。在后一种更简单的情况下,它就像

event1:{productId: 80, price: 500, oldPrice: 0}
event2:{productId: 80, price: 600, oldPrice: 500}
event3:{productId: 80, price: 400, oldPrice: 600}
event4:{productId: 80, price: 900, oldPrice: 400}
event5:{productId: 80, price: 100, oldPrice: 900}

如果基本状态不再匹配,这将使您的代码拒绝应用该操作。但这非常有限,您不希望在重新订购后一切都失败,您只需要收敛行为。这就是我大喊“矢量时钟”并跳出窗外的地方。设计分布式、融合系统确实非常困难,请以 CRDT 一词为起点。

于 2021-05-20T01:46:49.910 回答
0

我认为您的问题是由于不完全了解您的消息代理(可能是 NATS)的传递保证。

首先,您应该确定您需要哪种保证,然后选择一种消息传递技术。如果您需要对所有事件、关于一个实体的所有事件进行严格排序,或者根本不需要排序,这会产生巨大的差异。交付语义也是如此:最多一次,至少一次,精确一次。

如果这些事情很清楚,那么选择满足这些要求的消息传递技术,否则您最终会通过变通方法增加复杂性(如 coderanger 的建议)。那里有许多消息传递协议,例如 AMQP、MQTT、NATS、Kafka 等……

请注意,这是拥有分布式架构的成本!在做微服务时,没有办法考虑分布式系统的问题。

于 2021-05-20T08:42:45.367 回答