一条消息怎么被两个消费者消费

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一条消息怎么被两个消费者消费相关的知识,希望对你有一定的参考价值。

在保证MQ消息不重复的情况下,消费者消费消息成功后,在给MQ发送消息确认的时候出现了网络异常(或者是服务中断),MQ没有接收到确认,此时MQ不会将发送的消息删除,为了保证消息被消费,当消费者网络稳定后,MQ就会继续给消费者投递之前的消息。这时候消费者就接收到了两条一样的消息 参考技术A 如何保证消息不被重复消费,或者说如何保证消息幂等性。
rbbitmq,rocketmq,kafka,都有可能出现消息重复消费的情况,以kafka来说
kafka实际上有个offset的概念,就是每个消息写进去,都有一个offset,代表的消息的序号,然后consumer消费了数据之后,每隔一段时间(定期定时),会把自己消费过的offset提交一下,表示“我已经消费过了,下次重启之后,还是从上次消费到的offset来继续消费。

如果遇到意外情况,还没来得及提交offset,进程就被杀掉了,重启之后,可能有些消息要重复消费一次。

Amazon SQS:两个当前消费者使用相同的消息

【中文标题】Amazon SQS:两个当前消费者使用相同的消息【英文标题】:Amazon SQS: The same message is consumed by two current consumers 【发布时间】:2016-07-01 14:22:17 【问题描述】:

我有四个当前消费者在 Amazon AWS 上收听同一个队列。当从队列中拉出消息时,有时会出现相同的消息被两个不同的消费者消费。请看下面的日志:

18:01:46,515 [jmsContainer-2] 调试 - 收到来自队列的消息:ID:3698a927-930b-4d6a-aeca-f66922528792

18:02:12,825 [jmsContainer-3] 调试 - 收到来自队列的消息:ID:3698a927-930b-4d6a-aeca-f66922528792

我有一个具有 4 个并发使用者的 JMS 容器设置。我将可见性超时设置为 30 秒。

既然消息被container2收到了,那container3怎么还能访问呢?

JMS 容器是否在执行侦听器方法(handleMessage)之前或之后进行自动确认?

【问题讨论】:

Using many consumers in SQS Queue的可能重复 【参考方案1】:

亚马逊不保证使用 SQS 准确交付一次。他们保证“至少一次”交付。常见问题解答https://aws.amazon.com/sqs/faqs/

中解决了这个问题

您必须牢记这一点,并设计您的系统以优雅地处理重复的消息传递。

【讨论】:

从技术上讲确实如此,但我发现它非常很少见。例子应该很难找到。问题通常不是 SQS,而是用户组件重置可见性超时。 感谢您的解释。这实际上对我来说经常发生,而且我的应用程序代码中没有重置可见性超时。 如果消息的处理时间超过消息的不可见超时时间,则消息将重新出现在队列中并可供其他工作人员读取。这是重复消息的最常见原因。 @garnaat,但默认情况下,JMS 容器启用了自动确认,这意味着消息将在调用处理消息方法后立即被确认。如果我是正确的,那么 SQS 不必等到客户端处理完消息后才能删除消息。 如果 acknowledged 您的意思是从队列中删除,那么您是正确的。但是我当然希望消息的处理不会失败,因为它不会出现在重新处理队列中。【参考方案2】:

现在这可以通过 FIFO SQS 队列实现。您可以确保只有一个客户端接收到消息,然后在消息传输过程中将其删除

更多信息在这里:

https://aws.amazon.com/about-aws/whats-new/2016/11/amazon-sqs-introduces-fifo-queues-with-exactly-once-processing-and-lower-prices-for-standard-queues/

【讨论】:

以上是关于一条消息怎么被两个消费者消费的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ 如何保证消息不会被重复消费

Redis怎么做消息队列?

RocketMQ:消息ACK机制源码解析

kafka重复消费的原因

一文讲透 RocketMQ 消费者是如何负载均衡的

消息队列之kafka(消费语义)