dee*_* zg 1 concurrency azure race-condition azure-eventhub
当我们有事件中心(或任何消息服务)的多个使用者时,如何确保没有消息被处理两次,特别是在使用者自动扩展到多个实例的情况下?
我知道我们可以跟踪最后处理的消息,但话又说回来,在检查消息是否已处理和实际处理之间,其他实例已经可以处理它(竞争条件?。
那么,如何以可扩展的方式解决这个问题呢?
[更新] 我知道建议至少拥有与消费者一样多的分区,但是如果单个消费者无法处理定向到它的消息但需要扩展到多个实例,该怎么办?
每个处理器都租用一个分区,请参阅文档
事件处理器实例通常拥有并处理来自一个或多个分区的事件。分区的所有权均匀地分布在与事件中心和使用者组组合关联的所有活动事件处理器实例中。
因此,横向扩展不会导致重复的消息处理,因为新处理器无法租用已由另一个处理器处理的分区。
然后,关于您的评论:
我知道有人建议至少拥有与消费者一样多的分区
反之亦然:建议拥有与分区一样多的消费者。如果消费者的数量多于分区的数量,那么消费者将相互竞争以获得分区上的锁。
现在,关于重复消息,由于事件中心保证至少一次传递,因此您无能为力来阻止这种情况。提供最多一次交付的可扩展服务并不多,我知道如果您确实需要的话,Azure 服务总线队列确实可以提供此服务。
可能会出现什么会导致重复消息处理的问题。嗯,在处理消息时,处理器会执行一些检查点操作:偶尔它会将其位置存储在分区事件序列中(请记住,分区绑定到单个处理器)。现在,当处理器实例在两个检查点事件之间崩溃时,新实例将从最后一个检查点的位置恢复处理消息。这很可能会导致旧消息被再次处理。
如果读取器与分区断开连接,当它重新连接时,它将开始读取该消费者组中该分区的最后一个读取器先前提交的检查点。
因此,这意味着您需要确保您的处理逻辑是幂等的。如何,这取决于你,因为我不知道你的用例。
一种选择是跟踪每条单独的消息以查看它是否已被处理。如果您没有唯一的 ID 来检查,也许您可以生成整个消息的哈希值并与其进行比较。
| 归档时间: |
|
| 查看次数: |
3181 次 |
| 最近记录: |