亚马逊 SQS 消息多次投递

28
我知道为了实现广泛的可扩展性和可靠性,SQS需要进行大量的资源并行处理。即使是小队列,它也会使用冗余服务器,甚至将发布到队列中的消息存储为多个副本。这些因素防止了像RabbitMQ一样的精确一次性交付。我甚至见过已删除的消息被传送的情况。
对于开发人员来说,影响是他们需要准备好接收多个消息传递。亚马逊声称这不是问题,但如果是,则开发人员必须使用一些同步构造,例如数据库事务锁定或dynamo-db条件写入。这两者都会降低可扩展性。
问题是,在重复传递问题的情况下,消息不可见期功能如何实现?不能保证消息不可见。如果开发人员必须自己安排同步,那么不可见期的好处是什么?我甚至看到消息在应该不可见的情况下重新传递。
  1. 如何使用Amazon SQS实现“仅一次”消息传递的良好实践?
  2. http://aws.amazon.com/sqs/faqs/#How_many_times_will_I_receive_each_message|我会收到每条消息多少次?
  3. http://aws.amazon.com/sqs/faqs/#How_does_Amazon_SQS_allow_multiple_readers_to_access_the_same_message_queue_without_losing_messages_or_processing_them_many_times|Amazon SQS如何允许多个读者访问同一消息队列而不丢失或重复处理消息?
  4. http://aws.amazon.com/sqs/faqs/#Can_a_deleted_message_be_received_again|已删除的消息是否可以再次接收到?

我很好奇 - 我已经广泛地使用了SQS,从未遇到过这些问题。不确定是运气好还是我构建的应用程序和企业系统无论是否接收相同的消息都没有关系。您有关于此的文档参考吗? - Pete - MSFT
@PeterH.,我已经更新了问题并添加了参考资料。 - inquisitive
真尴尬 - 就在常见问题解答中!谢谢。请为我阅读文档。 - Pete - MSFT
1
SQS现在拥有FIFO队列,可以保证消息传递的精确一次性。请参阅http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues.html。 - Lophat
1
@danny,是的,一次几千个。在我看来,这似乎是一个突发事件。一旦开始重新传递,它会持续几秒钟。我在日志中发现了这样的事件集群。我使用了dynamodb +强一致性+条件写入来解决问题。 - inquisitive
显示剩余3条评论
1个回答

17
消息不可见性解决的问题与确保仅传递一次消息的问题不同。考虑在队列中对项目进行长时间运行操作的情况。如果处理器在操作期间出现故障,则不希望删除消息,而希望将其重新显示并由其他处理器再次处理。
因此,模式如下:
  1. 将项目写入队列
  2. 查看队列中的项目
  3. 标记项目为不可见
  4. 对项目执行进程
  5. 编写结果
  6. 从队列中删除项目
因此,无论您是否重复投递消息,仍然需要确保处理队列中的项目。如果在从队列中取出它时删除它,然后您的服务器死机,您可能会永久丢失该消息。它通过使用spot实例实现积极扩展,并确保(使用上述模式)您不会丢失消息。
但是-它不能保证一次性交付。但我认为它并不是为这个问题设计的。我也不认为这是一个不可克服的问题。在我们的情况下(我可以理解为什么以前从未注意到这些问题)-我们将结果写入S3。如果它用相同的数据覆盖了相同的文件,那没关系。当然,如果要将借记交易发送到银行账户,您可能需要某种相关ID......大多数系统已经具有这些内容。因此,如果获取重复的关联值,则引发异常并继续执行。
好问题。对我来说触发了一些想法。

1
因此,我明白message-invisibility旨在确保工作进程崩溃时不会出现单一交付失败的情况,而不是防止其他工作进程获取相同的任务。因为其他工作进程仍可能获得重复任务... 我的理解正确吗? - inquisitive
3
有点儿是,肯定是“超时并重新排队”。但我建议也可以是“试图防止其他工人”。如果可能的话,你不希望其他工人抢到它,因为如果他们这样做了,而你有一个团队,他们都会抢下一个项目。在大多数情况下,它会像“防止其他工人”一样运作,但这并不是保证的行为。 - Pete - MSFT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接