首页 文章

SQS的ApproximateReceiveCount有多准确

提问于
浏览
2

我有一个系统,其中多个工作程序并行使用标准SQS队列 .

我注意到,当我有相对大量的消息(即3百万)时,我最后的总处理数总是导致比消息总数多一些消息(大约30) . (0.001%~0.002%以上)

我怀疑这是因为“至少一次”交付:

亚马逊文档:即使您删除了邮件,也可能会收到邮件 . 如果在请求删除邮件时存储邮件副本的其中一个服务器不可用,则极少数情况下可能会发生这种情况 . 副本仍保留在服务器上,并可能在后续接收请求中再次返回给您 . 您应该将系统创建为幂等的,以便不止一次地接收特定消息不是问题 .

因此,我想在处理之前使用“ApproximateReceiveCount”来确定我的消息是否已被处理:

(Worker pseudocode)

List messages = sqs.receiveMessage()
for m in messages:
   if m.approximateReceiveCount > 1 then
      skip process
   else
      process as usual
end

我想知道这个“approximateReceiveCount”有多精确,我的重复数据删除逻辑是否依赖于它是一个好主意 .

注意:

我已经设置了一个死信队列来处理任何超过“默认可见性超时”(设置为1h)的消息 . 由于没有任何消息被放回死信,我认为额外的计数不是由于这个“超时”效应 .

1 回答

  • 3

    您无法可靠地使用 approximateReceiveCount 属性来消除重复消息 . 因为如果您收到消息,然后失败,您的 approximateReceiveCount 可能为1,但仍需要再次处理该消息 .

    使用SQS时,最佳做法是确保您的SQS消息处理是idempotent . 这意味着多次处理相同的消息将产生相同的结果 .

    这意味着什么取决于您的业务逻辑 .

    • 您可以跟踪SQS消息ID以确定它们是否已经处理过 .

    • 或者您可以在消息中使用其他ID来确定消息是否已经处理过 .

    • 或者您可以多次处理数据,每次都达到相同的结果 .

    由于处理,跟踪和可能的故障之间可能存在竞争条件,解决方案1或2可能难以可靠地实施 .

    解决方案3可能是最好的,因为在处理失败的情况下,您可能无法进行1或2次交易 .

    Issues with solutions 1 or 2

    例1:

    假设您的逻辑如下:

    • 从队列接收消息

    • 处理消息

    • 记录重复数据删除的消息

    • 从队列中删除消息

    但是,如果在步骤2和3之间失败,或者在步骤2和3之间由另一个处理器第二次收到消息,则重复数据删除逻辑失败 .

    例2:

    或者,假设您的逻辑如下:

    • 从队列接收消息

    • 记录重复数据删除的消息

    • 处理消息

    • 从队列中删除消息

    现在,如果您在步骤2之后或步骤3中失败(意味着处理永远不会正确完成),那么您将永远无法对邮件进行另一次正确处理 .

相关问题