如何解决MQ消息消费顺序问题

一般mq能够保证先到队列的消息按照顺序分发给消费者消费来保证顺序,可是一个队列有多个消费者消费的时候,那将失去这个保证,由于这些消息被多个线程并发的消费。可是有的时候消息按照顺序处理是很重要的,那咱们该如何来保证消息的顺序呢,下面将从activemq和rocketmq来看看,它们是如何来保证消息的顺序问题的?咱们还能够有别的处理方案么?网络

Activemq处理方案session

一、利用Activemq的高级特性:consumer之独有消费者(exclusive consumer)并发

在ActiveMQ4.x中能够采用Exclusive Consumer,broker会从queue中,一次发送消息给一个消费者,这样就避免了多个消费者并发消费的问题,从而保证顺序,配置以下:负载均衡

queue = new ActiveMQQueue("TEST.QUEUE?consumer.exclusive=true");
consumer = session.createConsumer(queue);
  • 当在接收信息的时候有一个或者多个备份接收消息者和一个独占消息者的同时接收时候,不管二者建立前后,在接收的时候,均为独占消息者接收。
  • 当在接收信息的时候,有多个独占消费者的时候,只有一个独占消费者能够接收到消息。
  • 当有多个备份消息者和多个独占消费者的时候,当全部的独占消费者均close的时候,只有一个备份消费者接到到消息。
  • 当主消费者挂了话,会马上启用故障切换转移到下一台消费者继续消费

图片描述

图1

独占消息就是在有多个消费者同时消费一个queue时,能够保证只有一个消费者能够消费消息,这样虽然保证了消息的顺序问题,不过也带来了一个问题,就是这个queue的全部消息将只会在这一个主消费者上消费,其余消费者将闲置,达不到负载均衡分配,而实际业务咱们可能更多的是这样的场景,好比一个订单会发出一组顺序消息,咱们只要求这一组消息是顺序消费的,而订单与订单之间又是能够并行消费的,不须要顺序,由于顺序也没有任何意义,有没有办法作到呢?答案是能够的,下面就来看看activemq的另外一个高级特性之messageGroup。分布式

二、利用Activemq的高级特性:messageGroupsspa

Message Groups特性是一种负载均衡的机制。在一个消息被分发到consumer以前,broker首先检查消息JMSXGroupID属性。若是存在,那么broker会检查是否有某个consumer拥有这个message group。若是没有,那么broker会选择一个consumer,并将它关联到这个message group。此后,这个consumer会接收这个message group的全部消息,直到:线程

  • Consumer被关闭
  • Message group被关闭,经过发送一个消息,并设置这个消息的JMSXGroupSeq为-1

图片描述

图2

配置以下:code

bytesMessage.setStringProperty("JMSXGroupID", "constact-20100000002");
bytesMessage.setIntProperty("JMSXGroupSeq", -1);

如上图所示,同一个queue中,拥有相同JMSXGroupID的消息将发往同一个消费者,解决顺序问题,不一样分组的消息又能被其余消费者并行消费,解决负载均衡的问题,一箭双鵰啦!server

  • 问题讨论,除了上述Activemq为咱们提供的方案,咱们是否不依赖这两种特性,也能解决顺序问题呢?

Rocketmq处理方案blog

那rocketmq又是如何保证消息顺序消费的问题呢?

Rocketmq跟传统的MQ有一点区别,这里有必要讲一下topic的概念,Topic是RocketMQ中的一个重要概念,RocketMQ的各组件都是围绕着Topic创建起对应关系的,在RocketMQ官方文档和本文中, Topic在不一样的语境下被赋予了两种不一样的语义:

1)消息的Topic属性值:在描述Consumer的订阅设置信息或消息的属性时。

2)Topic属性为某个值的消息(单个消息或消息集合):在描述Broker,Producer和Consumer的对应关系,Queue以及负载均衡策略时。

topic和queue的对应关系是一个topic拥有多个queue,当producer往broken发送消息时,消息会存储在topic下的不一样队列中,而一个队列只会被一个consumer消费,这样消息户被均衡负载到不一样的队列下,也就是会被多个消费者并行消费,顺序就没法保证了。该怎么办呢?答案是把须要顺序消费的消息发送到同一台broker server下的同一个队列,而这些消息也只会被同一个消费者消费,这样就能够保证严格的顺序了,以下图:

图片描述

一、消息要有顺序,首先得保证producer发送消息有顺序,如上图msg1,msg2,msg3发送到queue0是要有顺序的,只要producer等待前面的消息发送成功,在发送后面的消息就彻底能够保证了,

二、假设msg1发送给consumer1,消费没有响应,该怎么办呢?是继续发送msg2仍是从新发送msg1,通常为了保证消息必定被消费,确定会选择重发msg1到下一台消费者consumer2。

三、消费端1没有响应Server时有两种状况,一种是msg1确实没有到达(数据在网络传送中丢失),另一种消费端已经消费msg2且已经发送响应消息,只是MQ Server端没有收到。若是是第二种状况,重发msg1,就会形成msg1被重复消费。也就引入了消息重复问题,那就要幂等了。

Rocketmq一样作到了保证消息的顺序状况下,均衡消费的消费消息。

综上,我看到,在分布式系统中,要想消息有顺序的被消费,不管是Activemq仍是Rocketmq都要想办法让有顺序的消息被同一消费者消费,而不是并发的消费,在消费者消费成功后,接着才会消费下一个消息,这样就能够保证了严格的顺序。

相关文章
相关标签/搜索