Amazon web services 如何防止重复的SQS消息?

Amazon web services 如何防止重复的SQS消息?,amazon-web-services,amazon-sqs,Amazon Web Services,Amazon Sqs,在Amazon SQS中防止重复消息的最佳方法是什么?我有一个SQS的域名等待爬网。在我向SQS添加一个新域之前,我可以检查保存的数据,看看最近是否对其进行了爬网,以防止重复 问题在于尚未爬网的域。例如,如果队列中有1000个域尚未爬网。这些链接中的任何一个都可以一次又一次地添加。这将我的SQS扩展到数十万条消息,其中大部分是重复的 我如何防止这种情况?有没有办法从队列中删除所有重复项?或者,在添加消息之前,是否有方法在队列中搜索消息?我觉得这是任何拥有SQS的人都会遇到的问题 我可以看到的一个

在Amazon SQS中防止重复消息的最佳方法是什么?我有一个SQS的域名等待爬网。在我向SQS添加一个新域之前,我可以检查保存的数据,看看最近是否对其进行了爬网,以防止重复

问题在于尚未爬网的域。例如,如果队列中有1000个域尚未爬网。这些链接中的任何一个都可以一次又一次地添加。这将我的SQS扩展到数十万条消息,其中大部分是重复的

我如何防止这种情况?有没有办法从队列中删除所有重复项?或者,在添加消息之前,是否有方法在队列中搜索消息?我觉得这是任何拥有SQS的人都会遇到的问题


我可以看到的一个选项是,如果在将域添加到SQS之前存储一些数据。但是,如果我必须存储两次数据,那就有点破坏了首先使用SQS的意义。

没有API级别的方法来防止重复消息发布到SQS队列。恐怕您需要在应用程序级别处理此问题


您可以使用DynamoDB表来存储等待爬网的域名,并仅在域名不在DynamoDB中时将其添加到队列中。

正如前面提到的其他答案一样,您无法阻止来自SQS的重复消息

大多数情况下,您的信息会被传递给您的某个消费者一次,但在某个阶段,您会遇到重复的信息

我不认为这个问题有一个简单的答案,因为它需要一个合适的架构来处理重复,这意味着它本质上是幂等的

如果分布式体系结构中的所有worker都是幂等的,这将很容易,因为您不需要担心重复。但在现实中,这种环境并不存在,在这一过程中,某些东西将无法处理它

我目前正在进行一个项目,需要我解决这个问题,并提出一种处理方法。我想在这里分享我的想法可能对其他人有益。这可能是一个很好的地方,可以获得一些关于我想法的反馈

事实存储

开发服务是一个很好的主意,这样它们就可以收集事实,理论上可以在所有受影响的下游系统中重现相同的状态

例如,假设您正在为股票交易平台构建一个消息代理。(我以前确实做过这样一个项目,很糟糕,但也是一次很好的学习经历。)

现在让我们假设交易进入,有3个系统对此感兴趣:

  • 需要不断更新的老式大型机
  • 整理所有交易并在FTP服务器上与合作伙伴共享的系统
  • 记录交易并将股份重新分配给新所有者的服务
  • 这有点复杂,我知道,但我的想法是,一条消息(事实)传入,具有各种分布式下游效应

    现在让我们想象一下,我们维护一个事实存储,记录所有进入我们经纪人的交易。所有3个下游服务所有者都打电话告诉我们,他们已经丢失了过去3天的所有数据。FTP下载落后3天,主机落后3天,所有交易落后3天

    因为我们有事实存储,理论上我们可以从某个时间到某个时间重播所有这些消息。在我们的例子中,从3天前到现在。下游服务也可能被赶上

    这个例子似乎有点过头了,但我试图传达一个非常特别的信息:事实是需要跟踪的重要事情,因为这是我们将在体系结构中使用以对抗重复的地方

    事实存储如何帮助我们处理重复消息

    如果您在一个持久性层上实现了事实存储,该持久性层为您提供了系统的CA部分、一致性和可用性,那么您可以执行以下操作:

    一旦从队列接收到消息,您就可以在事实存储中检查您以前是否已看到此消息,如果已经看到,则检查该消息当前是否已锁定并处于挂起状态。在我的例子中,我将使用MongoDB实现我的事实存储,因为我对它非常熟悉,但是其他各种DB技术应该能够处理这个问题

    如果事实还不存在,它将被插入到事实存储中,并带有挂起状态和锁过期时间。这应该使用原子操作来完成,因为您不希望这种情况发生两次!这是您确保服务质量的地方

    幸福案例-大多数情况下都会发生

    当事实存储返回到您的服务,告诉它事实不存在,并且创建了一个锁时,服务会尝试执行它的工作。一旦完成,它将删除SQS消息,并将事实标记为已完成

    重复消息

    这就是当一条信息通过而不是重复时发生的情况。但是,让我们看看何时会出现重复消息。服务将其提取出来,并要求事实存储用锁记录下来。事实存储告诉它它已经存在,并且它已被锁定。服务忽略该消息并跳过它!消息处理完成后,另一个工作者将从队列中删除此消息,我们将不再看到它

    灾难案例-很少发生

    那么,当一个服务在商店中第一次记录了这个事实,然后在一段时间内获得了一个锁,但是失败了,会发生什么呢?SQS将再次向您呈现一条消息,如果它被拾取,但在从队列中送达后的某个时间段内未被删除。这就是为什么w
    var params = { 
        VisibilityTimeout: 20,
        ...
    };
    
    sqs.receiveMessage(params, function(err, data) {});