错乱消息出现的原因:
1.在RocketMq为啥消息不是按照顺序来的呢?
首先您需要了解、队列是一个先进先出的一个数据的结构
生产者: 您可以将topic理解为里面有一个一个的队列,你将一个消息发送到topic的时候,当前的消息不一定是往当前的这个topic中的哪一个队列发送的、倒是消息没有按照您的需求发送到指定的队列;
消费者: 在默认的情况下我们使用 new MessageListenerConcurrently()的话,是有多条线程在当前的一个队列当中来进行消息的获取,导致消息没有按照正常的顺序来进行消费;
2.解决方案:
生产者: provider需要将需要按照顺序发送的消息、发送到topic中的指定的一个队列;
消费者: 使用单条线程去队列中获取消息;
代码示例:
生产者:
public class QueueProvider {
public static void main(String[] args) throws Exception {
DefaultMQProducer defaultMQProducer = new DefaultMQProducer("group1");
defaultMQProducer.setNamesrvAddr("192.168.56.100:9876"); //设置nameServer的地址'
defaultMQProducer.start(); //开始;
getOrderList().forEach(t->{ //遍历数据集合;
Message message = new Message("texttopic","testTag", JSON.toJSONString(t).getBytes(StandardCharsets.UTF_8));
try {
SendResult send = defaultMQProducer.send(message, new MessageQueueSelector() {
@Override
public MessageQueue select(List list, Message message, Object o) {
int index = t.getId().toString().hashCode()%list.size(); //获取队列 使用%确保不会索引越界异常;
return list.get(index); //返回队列数据信息;
}
}, null);
System.out.println(send);
} catch (Exception e) {
e.printStackTrace();
}
});
}
public static List getOrderList() {
List orderList = new LinkedList<>();
Order orderOne = new Order();
orderOne.setId(1);
orderOne.setOrderCode(1);
orderOne.setMsg("一号");
Order orderTwo = new Order();
orderTwo.setId(1);
orderTwo.setOrderCode(2);
orderTwo.setMsg("二号");
Order orderThree = new Order();
orderThree.setId(1);
orderThree.setOrderCode(3);
orderThree.setMsg("三号");
orderList.add(orderOne);
orderList.add(orderTwo);
orderList.add(orderThree);
Order orderFove = new Order();
orderFove.setId(2);
orderFove.setOrderCode(1);
orderFove.setMsg("一号");
Order orderFive = new Order();
orderFive.setId(2);
orderFive.setOrderCode(2);
orderFive.setMsg("二号");
orderList.add(orderFove);
orderList.add(orderFive);
return orderList;
}
发送结果:
id相同的都放到了同一个队列当中去了;
SendResult [sendStatus=SEND_OK, msgId=FC0013E4496A00020000000000000CC41A1018B4AAC25B2B81100000, offsetMsgId=C0A8386400002A9F000000000000BCA8, messageQueue=MessageQueue [topic=texttopic, brokerName=broker-a, queueId=1], queueOffset=0]
SendResult [sendStatus=SEND_OK, msgId=FC0013E4496A00020000000000000CC41A1018B4AAC25B2B811B0001, offsetMsgId=C0A8386400002A9F000000000000BDA1, messageQueue=MessageQueue [topic=texttopic, brokerName=broker-a, queueId=1], queueOffset=1]
SendResult [sendStatus=SEND_OK, msgId=FC0013E4496A00020000000000000CC41A1018B4AAC25B2B811D0002, offsetMsgId=C0A8386400002A9F000000000000BE9A, messageQueue=MessageQueue [topic=texttopic, brokerName=broker-a, queueId=1], queueOffset=2]
SendResult [sendStatus=SEND_OK, msgId=FC0013E4496A00020000000000000CC41A1018B4AAC25B2B81200003, offsetMsgId=C0A8386400002A9F000000000000BF93, messageQueue=MessageQueue [topic=texttopic, brokerName=broker-a, queueId=2], queueOffset=0]
SendResult [sendStatus=SEND_OK, msgId=FC0013E4496A00020000000000000CC41A1018B4AAC25B2B81220004, offsetMsgId=C0A8386400002A9F000000000000C08C, messageQueue=MessageQueue [topic=texttopic, brokerName=broker-a, queueId=2], queueOffset=1]
消费者:
没一个队列只能有一个线程来进行服务;
代码示例:
package com.example.mqtt_client.queue;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly;
import org.apache.rocketmq.common.message.MessageExt;
import java.util.List;
public class Consumer {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer defaultMQPushConsumer = new DefaultMQPushConsumer("group1");
defaultMQPushConsumer.setNamesrvAddr("192.168.56.100:9876");
defaultMQPushConsumer.subscribe("texttopic","*");
defaultMQPushConsumer.registerMessageListener(new MessageListenerOrderly() {
@Override
public ConsumeOrderlyStatus consumeMessage(List list, ConsumeOrderlyContext consumeOrderlyContext) {
list.forEach(t->{
System.out.println(new String(t.getBody()));
});
return ConsumeOrderlyStatus.SUCCESS;
}
});
defaultMQPushConsumer.start();
}
}
接收到数据示例:
Connected to the target VM, address: '127.0.0.1:53941', transport: 'socket'
{"id":2,"msg":"一号","orderCode":1}
{"id":1,"msg":"一号","orderCode":1}
{"id":2,"msg":"二号","orderCode":2}
{"id":1,"msg":"二号","orderCode":2}
{"id":1,"msg":"三号","orderCode":3}