消息幂等性 - 排序考虑

4
假设我们有一个系统,其中一个生产者将消息排队到队列中,多个相同的消费者实例处理这些事件。由于我们处于竞争消费者模式中,因此不再保证排序。这意味着我们必须确保我们的消息是幂等的。
根据我在这里(在消息排序项目符号下)所读到的内容,我们必须确保消息处理是幂等的。
以下是问题:
  • 我们如何设计我们的消息处理程序是幂等的?
  • 如果我们将每个事件保存在事件存储中,那么在设计每个事件的有效负载和聚合事件以获取聚合状态时,是否需要考虑任何注意事项?
例如:假设我们有一个"用户创建"和"用户删除"消息(或任何其他需要按顺序处理的事件对)。如果我们在处理"用户删除"之前处理"用户创建",则用户将不会被删除。即使它们按事件队列中的顺序排列。是否真的可以通过幂等的处理/幂等的事件来删除用户? 另一个例子。 假设我们有一个带有score属性的实体。用户可以修改分数。第二个服务消耗“分数实体”服务的事件,如果分数达到100,则第二个服务将实体(或实体引用)插入“最佳类别”实体中。如果分数达到-20,则第二个服务将分数实体插入“更差的类别”中。如果有多个第二个服务的实例在“分数100”和“分数-20”事件在极短的时间间隔内发生,可能会产生不可预测的结果。如何设计“分数x”事件或如何处理这些事件?

非常感谢您的帮助!

1个回答

4
我们如何设计消息处理使其幂等性?
您应该:
- 忽略已经“看到”的消息;这意味着消费者应该有一种检测的方式;例如,它可以保持已经处理的消息ID列表(这意味着每个消息都应该有一个唯一的ID)。 - 如果消息没有改变状态,则不要抛出异常;例如,如果您收到第二个DeleteUser事件(因此用户已被删除,第二个删除不应产生任何副作用),则应忽略它。并非每个事件都可以是幂等的,例如UpdateUserName就不能是幂等的。
如果我们将每个事件保存在事件存储中,那么在设计每个事件的有效负载和聚合事件以获取聚合状态时是否需要考虑任何问题?
您应该根据您的领域设计事件;有效负载不应包含比领域所需的更多信息。如果附加信息能够使您的读取模型更容易实现,那么您可以将其添加到有效负载中,但请注意将其标记为冗余。
例如:假设我们有一个“创建用户”和一个“删除用户”消息(或其他一对需要按顺序处理的事件)。如果在处理“删除用户”之前处理“创建用户”,则用户将不会被删除,即使它们按事件队列排序。幂等处理/幂等事件真的可以为已删除的用户提供吗?
在这种特殊情况下,您可以拥有一个额外的已删除用户集合;您只能保留其ID。当CreateUser事件到达时,您可以通过查看DeletedUsers集合来检查用户是否已被删除,并在用户存在时忽略它。您可以忽略每个其他为该用户而来的事件。
本解决方案非常依赖于领域。
另一个例子。假设我们有一个实体具有分数属性。用户可以修改分数。第二个服务消耗“分数实体”服务的事件,如果分数达到100,则由第二个服务将实体(或实体引用)插入“最佳类别”实体中。如果分数达到-20,则第二个服务将分数实体插入“更差类别”中。如果“得分100”和“得分-20”事件在很短的时间间隔内出现,则多个第二个服务的实例可能会产生不可预测的结果。有关如何设计“得分x”事件或如何处理这些事件的任何想法吗?

这种情况可以通过保留/附加到readmodels(两个集合bestworse)中上次处理事件的时间戳/顺序/流版本/等等,并忽略小于或等于该时间戳的每个事件来解决。这样,如果“分数100”在“分数-20”之后发出但先到达,则应忽略“分数-20”,因为它具有较低的时间戳,即使它最后到达。

这种解决方案是通用的,但它依赖于某种排序存在。


所以,基本上一切都取决于你在做什么。而且每个解决方案的实施都是因情况而异,不是吗?最后一个问题。在竞争消费者模式中,当两个事件(它们持有时间戳元数据)依次发出但接收顺序不同时,是否会改变之前所说的任何内容?从我的角度来看,无序处理或无序接收(或两者兼有)在竞争消费者模式中都会导致相同的情况,我是对的吗? - Christian Paesante
@ChristianPaesante 一般来说,您需要在每个用例中思考并选择最佳解决方案。我观察到两种情况:这取决于两个事件是相互独立还是相互依存的。例如,一个事件可能是由另一个事件(直接或间接)引起的。当接收到无序事件时,独立事件不应该引起问题。相互依存的事件应根据用例进行特殊处理。您可以忽略较新的事件(例如在DeleteUser之后出现的CreateUser),或者当旧事件比正常时间晚到达时,您的读模型可以追赶上来。 - Constantin Galbenu
在结论中,我认为这个乱序问题没有通用的解决方案。 - Constantin Galbenu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接