RoctetMQ 如何保证顺序消费

1:背景

在一些特殊的场景下,需要保证消息的顺序性,rocketMQ 提供了确实有效的解决方法。需要发送端和消费端同时保证才行。
总结下来,需要满足下面几个条件:
1:同一个Topic
2:同一个Queue
3:发消息的时候用同一个线程发送消息
3:消费消息的时候用同一个线程消费一个 Queue 里面的消息,或者用提供的消息选择器 MessageListenerOrderly

2:发送端

示例代码:

    /**
     * 发送顺序消息
     */
    private static void orderSend(DefaultMQProducer producer) throws Exception {
        Message message = new Message("myTopic", "我发送的第一条消息".getBytes());
        // 消息 queue 选择器,向 topic 中的那个 queue 去写消息,返回选择好的 queue
        MessageQueueSelector selector = new MessageQueueSelector() {
            @Override
            // List<MessageQueue> mqs : topic 下的 queue 列表
            // Message msg : 具体要发的那条消息
            // Object arg :外面的 arg 参数,会被传递进来,自定义参数
            public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                //假设选择第一个 queue
                return mqs.get((Integer) arg);
            }
        };
        producer.send(message, selector, 1, 2000);

        // 或者使用提供的默认选择器实现
        //producer.send(message,new SelectMessageQueueByHash(),1);
        //producer.send(message,new SelectMessageQueueByRandom(),1);
        // 根据机房去路由选择:未实现,需要根据源码自己去实现
        //producer.send(message,new SelectMessageQueueByMachineRoom(),1);
    }

下面解释为什么要同一个 Topic,同一个 Queue,发消息的时候用同一个线程发送消息
原因:
rocketMQ 的物理结构上是没有 Topic 这个概念的,是以 Queue 为物理单位的,在逻辑上,一个 Topic 包含 4 个 Queue,Queue 队列大家都知道,FIFO,先进先出的队列。 因此在 同一个 Topic 下的 同一个 Queue 里是可以保证 消息发送的顺序性的。至于为什么用同一个线程来发送消息,是为了防止多线程环境下带来的不确定性。

3:消费端

示例代码:

    /**
     * 单线程监听器:保证消费消息的顺序性, 对一个 Queue 开启一个线程
     */
    private static void oneCost(DefaultMQPushConsumer consumer){
        // 设置开启消费线程数,最大和最小
        //consumer.setConsumeThreadMax();
        //consumer.setConsumeThreadMin();
        consumer.registerMessageListener(new MessageListenerOrderly() {
            @Override
            public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {
                // 消费消息
                consumerMessage(msgs);
                return ConsumeOrderlyStatus.SUCCESS;
            }
        });
    }

MessageListenerConcurrently 是并发的开启多个线程为同一个 Queue 消费消息,MessageListenerOrderly 只为每一个 Queue 开启一个线程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值