如何在Amazon SQS中实现“仅一次交付”行为的良好实践是什么?

25
根据文档: “Q: 每条消息会被接收几次? Amazon SQS被设计为提供其队列中所有消息的“至少一次”传递。虽然大多数情况下每个消息将仅传递到您的应用程序一次,但您应该设计系统,使得重复处理一条消息不会创建任何错误或不一致性。”
如何实现精确一次性交付?是否有良好的做法? 我想使用DynamoDB的“条件写入”作为分布式锁定机制,但还有更好的方法吗?
一些关于此主题的参考资料: - 至少一次交付 (服务行为) - 精确一次性交付 (服务行为)

9
顺便说一句,最终我使用了“DynamoDB条件写入”。 - Filippo Vitale
以下文章很好地总结了解决方案(幂等 vs 使用锁)https://www.linkedin.com/pulse/20141207212332-99334190-solving-at-least-once-delivery-from-sqs - Ben Yitzhaki
4个回答

10

4
FIFO 队列与 SNS 不兼容,因此如果您正在使用 SNS+SQS 组合,就无法使用它。 - Gustavo Preciado
3
如果所有参与方(生产者、队列和消费者)都是单线程的,AWS FIFO队列只提供一次性交付。建议阅读本文了解更多信息-https://www.linkedin.com/pulse/truth-aws-sqs-fifo-harleen-mann/ - human

9
最佳解决方案取决于在多大程度上需要避免执行建议的操作。对于某些操作,例如删除文件或调整图像大小,如果发生两次并不重要,因此可以不采取任何行动。当更关键的是不要第二次执行工作时,我为每个消息使用标识符(由发送者生成),接收方通过在memchachd中标记这些id来跟踪副本。对于许多事情来说很好,但如果生命或钱财取决于此,尤其是存在多个使用者,则可能不太可行。
条件写入听起来像是一个聪明的解决方案,但我在想,如果您需要一个强大、精确地一次性的解决方案,那么AWS是否真的适合您的问题。

6
+1 我同意,亚马逊为了 sqs 的性能弱化做出的权衡使其不再是许多类型应用程序的消息传递解决方案。我希望他们能提供自己的同步解决方案作为可选行为,你可以在理解性能成本的前提下启用它,而不是我们所有人都必须花费时间去研究相同的解决方法。 - Jerico Sandhorn

4

另一种分布式锁的替代方案是 Redis 集群,也可以通过 AWS ElasticCache 进行配置。Redis 支持 事务,确保并发调用按顺序执行。

使用缓存的一个优点是您可以设置过期时间,因此如果消息处理失败,锁将在超时后被释放。


1
在这篇博客文章中,也推荐使用低延迟控制数据库,例如Amazon DynamoDB: https://aws.amazon.com/blogs/compute/new-for-aws-lambda-sqs-fifo-as-an-event-source/

Amazon SQS FIFO队列确保处理顺序遵循消息组内的消息顺序。但是,当用作Lambda触发器时,它不能保证仅一次传递。如果您的无服务器应用程序中仅需要一次传递,则建议使函数幂等。您可以通过使用可扩展的、低延迟的控制数据库,如Amazon DynamoDB,跟踪消息的唯一属性来实现这一点。

简而言之 - 我们可以使用条件表达式attribute_not_exists(对于put)或if_not_exists(对于update)在dynamodb表中放置或更新项目,请在此处查看示例 https://dev59.com/MFMI5IYBdhLWcg3w4Po_#55110463

如果在put/update操作期间出现异常,我们必须在lambda中返回而不进行进一步处理,否则就处理消息(https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/)

以下资源对我也很有帮助:

https://ably.com/blog/sqs-fifo-queues-message-ordering-and-exactly-once-processing-guaranteed

https://aws.amazon.com/blogs/aws/introducing-amazon-sns-fifo-first-in-first-out-pub-sub-messaging/

https://youtu.be/8zysQqxgj0I


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