SQS 的 ApproximateReceiveCount 有多准确

hel*_*rry 4 amazon-sqs amazon-web-services

我有一个系统,其中多个工作人员并行使用标准 SQS 队列。

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

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

Amazon Doc:即使您删除了它,您也可能会收到一条消息。如果在您请求删除邮件时存储邮件副本的其中一台服务器不可用,这种情况可能会在极少数情况下发生。该副本保留在服务器上,并且可能会在后续接收请求中再次返回给您。您应该将系统创建为幂等的,以便多次接收特定消息不会有问题。

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

(Worker pseudocode)

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

我想知道这个“approximateReceiveCount”有多准确,以及让我的重复数据删除逻辑依赖于它是否是个好主意。

注意:

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

Mat*_*ser 6

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

使用 SQS 时,最佳实践是确保您的 SQS 消息处理是幂等的。这意味着多次处理相同的消息将产生相同的结果。

这意味着什么完全取决于您的业务逻辑。

  1. 您可以跟踪 SQS 消息 ID 以确定它们是否已被处理。
  2. 或者,您可以在消息中使用其他一些 ID 来确定消息是否已被处理。
  3. 或者您可以多次处理数据,每次都达到相同的结果。

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

解决方案 3 可能是最好的,因为在处理失败的情况下,您可能无法实际执行 1 或 2。

解决方案 1 或 2 的问题

示例 1:

假设你的逻辑如下:

  1. 从队列接收消息
  2. 处理消息
  3. 记录重复数据删除消息
  4. 从队列中删除消息

但是,如果您在第 2 步和第 3 步之间失败,或者在第 2 步和第 3 步之间另一个处理器再次收到消息,那么您的重复数据删除逻辑就失败了。

示例 2:

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

  1. 从队列接收消息
  2. 记录重复数据删除消息
  3. 处理消息
  4. 从队列中删除消息

现在,如果您在第 2 步之后或在第 3 步期间失败(意味着处理永远不会正确完成),那么您将永远无法再次正确处理您的消息。