RocketMq顺序发送消息

错乱消息出现的原因:

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<MessageQueue> 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<Order> getOrderList() {
        List<Order> 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<MessageExt> 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}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值