ROCKETMQ——顺序消费示例

摘要

局部顺序消费:可以保证路由到同一个队列的消息是被顺序消费的。

全局顺序消费:让所有消息路由到同一个队列,这样就可以保证全局消费是顺序的。

这两种顺序,只是Producer指定队列的地方不一样,其它的都一样的。

示例

先看个简单的,全局顺序消费。同一个topic的所有消息是顺序消费的。

全局顺序消费

Producer

public class Producer {
    public static void main(String[] args) throws UnsupportedEncodingException {
        try {
        	DefaultMQProducer   producer = new DefaultMQProducer("please_rename_unique_group_name");
            producer.setNamesrvAddr("10.201.9.65:9876;10.201.9.67:9876");
            producer.start();

            String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"};
            for (int i = 0; i < 10; i++) {
                int orderId = i % 10;
                Message msg =
                    new Message("TopicTest", tags[i % tags.length], "KEY" + i,
                        ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
                SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
					/**
					 * 全局顺序、局部顺序差别就在这里。
					 * mqs 表示所有的队列
					 * msg 消息
					 * arg 传进来的参数的,根据这个参数选定队列。本示例传进来的就是固定的0队列。下个局部顺序示例,这里就是动态的参数i
					 */
                    @Override
                    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                        Integer id = (Integer) arg;
                        int index = id % mqs.size();
                        return mqs.get(index);
                    }
                }, 0);

                System.out.println("队列ID:"+ sendResult.getMessageQueue().getQueueId());
            }

            producer.shutdown();
        } catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Consumer

两个同样的Consumer示例(Consumer,Consumer2)

public class Consumer {

    public static void main(String[] args) throws MQClientException {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_3");
        consumer.setNamesrvAddr("10.201.9.65:9876;10.201.9.67:9876");
        
        /**
         * 设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费<br>
         * 如果非第一次启动,那么按照上次消费的位置继续消费
         */
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        consumer.subscribe("TopicTest", "TagA || TagC || TagD");
        consumer.registerMessageListener(new MessageListenerOrderly() {
            AtomicLong consumeTimes = new AtomicLong(0);

            @Override
            public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {

                this.consumeTimes.incrementAndGet();
                context.setAutoCommit(true);
            	System.out.println("当前时间:"+System.currentTimeMillis()+"接收到消息,队列ID:"+context.getMessageQueue().getQueueId());
            	for(MessageExt msg:msgs){
            		System.out.println("消息内容为:"+new String(msg.getBody()));
            	}
                return ConsumeOrderlyStatus.SUCCESS;
            }
        });
        consumer.start();
        System.out.printf("Consumer Started.%n");
    }
}

结果分析

分析下面结果,消息都发送到同一个队列(0号队列,默认一般会有4条队列),所有消息都被Consumer给顺序消费了。

producer
消息内容:Hello RocketMQ 0
队列ID:0
消息内容:Hello RocketMQ 1
队列ID:0
消息内容:Hello RocketMQ 2
队列ID:0
消息内容:Hello RocketMQ 3
队列ID:0
消息内容:Hello RocketMQ 4
队列ID:0
消息内容:Hello RocketMQ 5
队列ID:0
消息内容:Hello RocketMQ 6
队列ID:0
消息内容:Hello RocketMQ 7
队列ID:0
消息内容:Hello RocketMQ 8
队列ID:0
消息内容:Hello RocketMQ 9
队列ID:0
Consumer
当前时间:1545659825114接收到消息,队列ID:0
消息内容为:Hello RocketMQ 0
当前时间:1545659825172接收到消息,队列ID:0
消息内容为:Hello RocketMQ 1
当前时间:1545659825232接收到消息,队列ID:0
消息内容为:Hello RocketMQ 2
当前时间:1545659825289接收到消息,队列ID:0
消息内容为:Hello RocketMQ 3
当前时间:1545659825344接收到消息,队列ID:0
消息内容为:Hello RocketMQ 4
当前时间:1545659825406接收到消息,队列ID:0
消息内容为:Hello RocketMQ 5
当前时间:1545659825473接收到消息,队列ID:0
消息内容为:Hello RocketMQ 6
当前时间:1545659825536接收到消息,队列ID:0
消息内容为:Hello RocketMQ 7
当前时间:1545659825604接收到消息,队列ID:0
消息内容为:Hello RocketMQ 8
当前时间:1545659825662接收到消息,队列ID:0
消息内容为:Hello RocketMQ 9

Consumer2

结果为空,没有任何消费

分区顺序消费

分区顺序消费,是在同一个队列里面的消息,按照顺序消费,但是在不同队列里面的消息,则不一定按顺序消费。

Producer

public class Producer {
    public static void main(String[] args) throws UnsupportedEncodingException {
        try {
        	DefaultMQProducer   producer = new DefaultMQProducer("please_rename_unique_group_name");
            producer.setNamesrvAddr("10.201.9.65:9876;10.201.9.67:9876");
            producer.start();

            String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"};
            for (int i = 0; i < 10; i++) {
                int orderId = i % 10;
                Message msg =
                    new Message("TopicTest", tags[i % tags.length], "KEY" + i,
                        ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
                SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
                    @Override
                    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                        Integer id = (Integer) arg;
                        int index = id % mqs.size();
                        return mqs.get(index);
                    }
                }, 0);

                System.out.println("队列ID:"+ sendResult.getMessageQueue().getQueueId());
            }

            producer.shutdown();
        } catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Consumer

跟上面consumer代码一样

Consumer2

跟上面的Consumer代码一样

结果分析

producer 按照轮训的方式把消息发送到四个队列,consumer将消息安好队列归类,发现同一个队列里面的消息还是按照顺序消费的。

Producer结果
消息内容:Hello RocketMQ 0
队列ID:0
消息内容:Hello RocketMQ 1
队列ID:1
消息内容:Hello RocketMQ 2
队列ID:2
消息内容:Hello RocketMQ 3
队列ID:3
消息内容:Hello RocketMQ 4
队列ID:0
消息内容:Hello RocketMQ 5
队列ID:1
消息内容:Hello RocketMQ 6
队列ID:2
消息内容:Hello RocketMQ 7
队列ID:3
消息内容:Hello RocketMQ 8
队列ID:0
消息内容:Hello RocketMQ 9
队列ID:1
Consumer结果
当前时间:1545659891805接收到消息,队列ID:0
消息内容为:Hello RocketMQ 0
当前时间:1545659891866接收到消息,队列ID:1
消息内容为:Hello RocketMQ 1
当前时间:1545659891926接收到消息,队列ID:2
消息内容为:Hello RocketMQ 2
当前时间:1545659891984接收到消息,队列ID:3
消息内容为:Hello RocketMQ 3
当前时间:1545659892332接收到消息,队列ID:0
消息内容为:Hello RocketMQ 8
当前时间:1545659892392接收到消息,队列ID:1
消息内容为:Hello RocketMQ 9
Consumer2结果
当前时间:1545659892099接收到消息,队列ID:0
消息内容为:Hello RocketMQ 4
当前时间:1545659892159接收到消息,队列ID:1
消息内容为:Hello RocketMQ 5
当前时间:1545659892219接收到消息,队列ID:2
消息内容为:Hello RocketMQ 6
当前时间:1545659892290接收到消息,队列ID:3
消息内容为:Hello RocketMQ 7

Consumer 和 Consumer2 结果按照队列归类
队列0
Consumer
当前时间:1545659891805接收到消息,队列ID:0
消息内容为:Hello RocketMQ 0
Consumer2
当前时间:1545659892099接收到消息,队列ID:0
消息内容为:Hello RocketMQ 4

队列1
Consumer
当前时间:1545659891866接收到消息,队列ID:1
消息内容为:Hello RocketMQ 1

Consumer2
当前时间:1545659892159接收到消息,队列ID:1
消息内容为:Hello RocketMQ 5

Consumer
当前时间:1545659892392接收到消息,队列ID:1
消息内容为:Hello RocketMQ 9



队列2
Consumer
当前时间:1545659891926接收到消息,队列ID:2
消息内容为:Hello RocketMQ 2
Consumer2
当前时间:1545659892219接收到消息,队列ID:2
消息内容为:Hello RocketMQ 6

队列3
Consumer
当前时间:1545659891984接收到消息,队列ID:3
消息内容为:Hello RocketMQ 3
Consumer2
当前时间:1545659892290接收到消息,队列ID:3
消息内容为:Hello RocketMQ 7队列0
Consumer
当前时间:1545659891805接收到消息,队列ID:0
消息内容为:Hello RocketMQ 0
Consumer2
当前时间:1545659892099接收到消息,队列ID:0
消息内容为:Hello RocketMQ 4

队列1
Consumer
当前时间:1545659891866接收到消息,队列ID:1
消息内容为:Hello RocketMQ 1

Consumer2
当前时间:1545659892159接收到消息,队列ID:1
消息内容为:Hello RocketMQ 5

Consumer
当前时间:1545659892392接收到消息,队列ID:1
消息内容为:Hello RocketMQ 9



队列2
Consumer
当前时间:1545659891926接收到消息,队列ID:2
消息内容为:Hello RocketMQ 2
Consumer2
当前时间:1545659892219接收到消息,队列ID:2
消息内容为:Hello RocketMQ 6

队列3
Consumer
当前时间:1545659891984接收到消息,队列ID:3
消息内容为:Hello RocketMQ 3
Consumer2
当前时间:1545659892290接收到消息,队列ID:3
消息内容为:Hello RocketMQ 7

转载于:https://my.oschina.net/liangxiao/blog/2992706

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值