【问题标题】:What happens if I delete an SQS Message that another consumer has received?如果我删除另一个消费者收到的 SQS 消息会怎样?
【发布时间】:2017-03-22 01:19:20
【问题描述】:

我有一个消费者,我怀疑它处理给定消息的时间比默认消息可见性要长,但最终成功了。

  • 如果Consumer A 收到消息R1M1 的收据M1
  • 然后可见性超时结束
  • 然后Consumer B 收到消息R2M1 的收据M1
  • 然后Consumer A 调用deleteMessage(R1M1)

消息是否被删除,或者它是否保留在队列中,因为另一个消费者有一个更有效的消息收据?

我观察到我的队列中的许多更复杂的消息都有很多 (50-1000) 个收据,但我没有记录任何处理消息的失败。我怀疑我多次成功处理每条消息,然后删除操作静默失败。

【问题讨论】:

    标签: amazon-web-services amazon-sqs


    【解决方案1】:

    API 参考文档实际上自相矛盾on the same page 关于这一点。

    删除消息

    从指定队列中删除指定消息。您可以使用消息的接收句柄来指定消息,而不是使用发送消息时收到的 MessageId

    即使消息由于可见性超时设置而被另一个阅读器锁定,它仍然会从队列中删除。

    这似乎很简单,直到您继续阅读。

    注意

    接收句柄与接收消息的特定实例相关联。如果您多次收到一条消息,那么您每次收到该消息时得到的回执句柄是不同的。如果您在使用DeleteMessage 操作时未提供消息的最新接收句柄,则请求成功,但消息可能不会被删除。

    因此,您的问题的答案是“是的,绝对是,但不是,不一定。”

    但它确实解释了为什么会出现静默失败——如果请求有效,删除显然不会失败。

    这可能是 SQS 分布式特性的一个基本产物——如果 SQS 内传递消息的特定节点发生故障,则可能是旧的消息回执可能会丢失。当然,我是在猜测。

    不过,从根本上说,如果您遇到这种情况,您似乎确实存在设计缺陷。您要么发送后续请求以增加可见性超时,要么将默认可见性超时设置得足够高,使其在正常情况下永远不会发生。最大值为 12 小时,这对于大多数用例来说太长了。

    此外,您的消费者需要一种方法来验证消息是否已被执行。

    将可见性超时视为重试计时器。

    我的基础架构中的一个示例是一个系统,它对被放入 S3 中的临时暂存桶的文件做出反应。队列使用者查找该文件,并执行一些数据库查询以确定哪个或哪些系统可能需要该文件。然后它将文件复制到目标系统存储桶,并且根据规则,它可以创建数据库条目和/或将消息发送到不同的队列以处理该文件。这通常会在短短几秒钟内发生,如果一切顺利,消息就会从队列中删除。如果出现问题,它就会忘记消息并返回轮询队列。

    此队列的默认可见性超时设置为 5 分钟,这比该过程通常需要的时间长得多,因为这是我希望在处理失败时重试消息的时间。这就是您想要使用可见性超时的方式。

    请注意,在标准处理条件下,正常模式处理永远不需要 5 分钟。

    重试 5 次后,SQS 将消息从主队列中移除,并将消息丢弃到死信队列中(您可以选择数字,我的设置是 5)。此队列由存储消息的单独进程使用,并提醒我该消息已超过其允许的接收次数并且从未被删除 - 指示毒丸消息或某种未处理的错误或慢性衰竭状态。

    【讨论】:

      猜你喜欢
      • 2020-10-16
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-03
      相关资源
      最近更新 更多