比方说,我们有一个系统,有一个生产者在队列中排队消息,并且同一消费者的多个实例处理此事件。 由于我们处于“竞争消费者”模式,因此我们知道不再保证订购。这意味着我们必须确保我们的信息是幂等的。
根据我读到的here(在消息顺序的要点下),我们必须确保消息处理是幂等的。
以下是问题:
一个示例:假设我们有一个“用户创建”和“用户删除”消息(或需要按顺序处理的任何其他事件)。如果我们在“用户创建”之前处理“用户删除”,则不会删除该用户。即使他们在事件队列中被订购。真幂等处理/幂等事件真的可以提供给已删除的用户吗?
另一个示例。
假设我们有一个具有score
属性的实体。用户可以修改分数。第二服务消耗“得分实体”服务的事件,并且如果得分达到100,则该实体(或实体参考)由第二服务插入“最佳类别”实体中。如果得分达到-20,则第二项服务将得分实体插入“更差的类别”。如果“得分100”和“得分-20”事件在很短的时间间隔内,则具有多个实例的第二个服务可以给出不可预测的结果。关于如何设计“得分x”事件或如何处理这些事件的任何想法?
非常感谢您的帮助!
答案 0 :(得分:2)
我们如何将消息处理设计为幂等的?
您应该:
DeleteUser
事件(因此该用户已被删除,则第二个删除应该没有副作用),然后您将其忽略。并非每个事件都可以是幂等的,例如UpdateUserName
不应是幂等的。如果我们将每个事件保存在事件存储中,那么在设计每个事件的有效负载和事件聚合以获取聚合状态时,是否需要考虑任何因素?
您应根据您的域设计事件;有效负载不应包含的信息超过域所需的信息。如果其他信息使您的readmodels实现更容易,则可以将其添加到有效负载中,但要小心以某种方式将其标记为冗余。
一个例子:假设我们有一个“用户创建的”和“用户删除的”消息(或任何其他需要按顺序处理的事件)。如果我们在“用户创建”之前处理“用户删除”,则不会删除该用户。即使他们在事件队列中被订购。真幂等处理/幂等事件真的可以提供给已删除的用户吗?
在这种情况下,您可以具有已删除用户的其他集合;您只能保留他们的ID。当CreateUser
事件到来时,您可以通过查看DeletedUsers
集合来查看用户是否已被删除,如果用户在那里,则将其忽略。您可以忽略该用户遇到的所有其他事件。
此解决方案非常依赖域。
另一个例子。假设我们有一个具有score属性的实体。用户可以修改分数。第二服务消耗“得分实体”服务的事件,并且如果得分达到100,则该实体(或实体参考)由第二服务插入“最佳类别”实体中。如果得分达到-20,则第二项服务将得分实体插入“更差的类别”。如果“得分100”和“得分-20”事件在很短的时间间隔内,则具有多个实例的第二个服务可以给出不可预测的结果。关于如何设计“得分x”事件或如何处理这些事件的任何想法?
这种情况可以通过以下方式解决:将内置/附加的读取模型(两个集合,best
和worse
)保留在时间戳/顺序/流版本/上一次处理的事件中并忽略每个小于或等于该时间戳记的事件。这样,如果“ score -20”之后发出“ score 100”但首先到达,则您应该忽略“ score -20”,因为它的时间戳比较短,尽管倒数第二。
此解决方案是通用的,但它依赖于某些排序的存在。