当 pod 有多个副本时如何处理多个更新事件

How to handle multiple update event when there is more then one replica of a pod

我有两个服务名称产品和订单。 OrderDb 中的 Order table 有 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。

这通常取决于您的数据库。我看到你把 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}

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

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

首先,您应该弄清楚您需要哪些保证,然后再选择一种消息传递技术。如果您需要对所有事件进行严格排序,对与一个实体有关的所有事件进行严格排序,或者根本不进行排序,这将产生巨大的不同。传递语义也是如此:至多一次、至少一次、恰好一次。

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

请注意,这是分布式架构的代价!做微服务就绕不开分布式系统的问题