系列九、Java操作RocketMQ之顺序消息

一、概述

        消息有序指的是可以按照消息发送的顺序来消费(FIFO),RocketMQ可以严格的保证消息有序,按照分区的不同,可以分为分区有序和全局有序。顺序消费的原理解析,在默认情况下消息发送会按照轮询的方式把消息发送到不同的Queue中(说明:一个Broker中有四个Queue),消费者消费消息的时候会从多个Queue上拉取消息,这种情况下消费者是无法顺序消费生产者发送的消息的。但是如果控制发送的顺序消息只依次发送到同一个Queue中,那么消费的时候只能从这个Queue上拉取,这种方式即为全局有序,虽然保证了顺序消费,但是效率比较低。再说说分区有序,分区有序是指有多个Queue参与,相对于每个Queue,消息都是有序的,可以类比当前网购的流程,一般都是:创建订单==》扣减库存==》增加积分,下面参考案例代码

二、案例代码

2.1、pom

        同案例五

2.2、RocketMQConstant

        同案例五

2.3、消费者

2.3.1、DLJDOrderConsumer1

package org.star.orderly.consumer;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
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 org.star.constants.RocketMQConstant;

import java.util.List;

/**
 * @Author: 一叶浮萍归大海
 * @Date: 2023/8/25 16:23
 * @Description: 顺序消息消费者
 */
@Slf4j
public class DLJDOrderConsumer1 {

    public static void main(String[] args) throws Exception {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("DLJDOrderConsumerGroup");
        consumer.setNamesrvAddr(RocketMQConstant.NAME_SERVER_ADDR);
        consumer.subscribe("DLJDOrderTopic", "*");
        consumer.registerMessageListener(new MessageListenerOrderly() {
            @Override
            public ConsumeOrderlyStatus consumeMessage(List list, ConsumeOrderlyContext consumeOrderlyContext) {
                if (CollectionUtils.isNotEmpty(list)) {
                    list.forEach(e -> {
                        log.info("我是消费者DLJDOrderConsumer1,当前线程:{},队列ID:{},收到消息:{}",Thread.currentThread().getName(),e.getQueueId(), StrUtil.utf8Str(e.getBody()));
                    });
                }
                return ConsumeOrderlyStatus.SUCCESS;
            }
        });
        consumer.start();
        log.info("DLJDOrderConsumer1 start success");
    }

}

2.3.2、DLJDOrderConsumer2

package org.star.orderly.consumer;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
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 org.star.constants.RocketMQConstant;

import java.util.List;

/**
 * @Author: 一叶浮萍归大海
 * @Date: 2023/8/25 16:23
 * @Description: 顺序消息消费者
 */
@Slf4j
public class DLJDOrderConsumer2 {

    public static void main(String[] args) throws Exception {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("DLJDOrderConsumerGroup");
        consumer.setNamesrvAddr(RocketMQConstant.NAME_SERVER_ADDR);
        consumer.subscribe("DLJDOrderTopic", "*");
        consumer.registerMessageListener(new MessageListenerOrderly() {
            @Override
            public ConsumeOrderlyStatus consumeMessage(List list, ConsumeOrderlyContext consumeOrderlyContext) {
                if (CollectionUtils.isNotEmpty(list)) {
                    list.forEach(e -> {
                        log.info("我是消费者DLJDOrderConsumer2,当前线程:{},队列ID:{},收到消息:{}",Thread.currentThread().getName(),e.getQueueId(), StrUtil.utf8Str(e.getBody()));
                    });
                }
                return ConsumeOrderlyStatus.SUCCESS;
            }
        });
        consumer.start();
        log.info("DLJDOrderConsumer2 start success");
    }

}

2.4、DLJDOrderProducer

package org.star.orderly.producer;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.star.constants.RocketMQConstant;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @Author: 一叶浮萍归大海
 * @Date: 2023/8/25 16:14
 * @Description: 顺序消息生产者
 */
@Slf4j
public class DLJDOrderProducer {

    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("DLJDOrderProducerGroup");
        producer.setNamesrvAddr(RocketMQConstant.NAME_SERVER_ADDR);
        try {
            producer.start();
            // 模拟6笔订单
            for (Integer orderId = 1; orderId <= 6; orderId++) {
                // 每笔订单要发送3条消息,即:创建订单==》扣减库存==》增加积分
                for (int j = 0; j < 3; j++) {
                    String data = "";
                    switch (j % 3) {
                        case 0:
                            data = "创建订单,订单id:" + orderId;
                            break;
                        case 1:
                            data = "扣减库存,订单id:" + orderId;
                            break;
                        case 2:
                            data = "增加积分,订单id:" + orderId;
                            break;
                    }
                    Message message = new Message("DLJDOrderTopic", "DLJDOrderTag", orderId.toString(), data.getBytes(StandardCharsets.UTF_8));
                    producer.send(message, new MessageQueueSelector() {
                        @Override
                        public MessageQueue select(List messageQueues, Message message, Object o) {
                            int hashCode = message.getKeys().hashCode();
                            int size = messageQueues.size();    // 队列的数量
                            int index = hashCode % size;         // 队列的索引
                            log.info("keys:{},hashCode:{},size:{},index:{},messageQueues:{}", message.getKeys(), hashCode, size, index, JSON.toJSONString(message));
                            log.info("当前操作:{}", StrUtil.utf8Str(message.getBody()));
                            return messageQueues.get(index);
                        }
                    }, orderId);
                }
            }
            log.info("DLJDOrderProducer start success");
            producer.shutdown();
        } catch (Exception e) {
            log.error("error:{}", e.getMessage());
        }
    }

}

2.5、控制台打印

# 生产者端
22:03:41.819 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:1,hashCode:49,size:4,index:1,messageQueues:{"body":"5Yib5bu66K6i5Y2V77yM6K6i5Y2VaWTvvJox","delayTimeLevel":0,"flag":0,"keys":"1","properties":{"KEYS":"1","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:41.829 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:创建订单,订单id:1
22:03:43.235 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:1,hashCode:49,size:4,index:1,messageQueues:{"body":"5omj5YeP5bqT5a2Y77yM6K6i5Y2VaWTvvJox","delayTimeLevel":0,"flag":0,"keys":"1","properties":{"KEYS":"1","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.235 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:扣减库存,订单id:1
22:03:43.241 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:1,hashCode:49,size:4,index:1,messageQueues:{"body":"5aKe5Yqg56ev5YiG77yM6K6i5Y2VaWTvvJox","delayTimeLevel":0,"flag":0,"keys":"1","properties":{"KEYS":"1","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.241 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:增加积分,订单id:1
22:03:43.243 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:2,hashCode:50,size:4,index:2,messageQueues:{"body":"5Yib5bu66K6i5Y2V77yM6K6i5Y2VaWTvvJoy","delayTimeLevel":0,"flag":0,"keys":"2","properties":{"KEYS":"2","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.244 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:创建订单,订单id:2
22:03:43.247 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:2,hashCode:50,size:4,index:2,messageQueues:{"body":"5omj5YeP5bqT5a2Y77yM6K6i5Y2VaWTvvJoy","delayTimeLevel":0,"flag":0,"keys":"2","properties":{"KEYS":"2","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.247 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:扣减库存,订单id:2
22:03:43.250 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:2,hashCode:50,size:4,index:2,messageQueues:{"body":"5aKe5Yqg56ev5YiG77yM6K6i5Y2VaWTvvJoy","delayTimeLevel":0,"flag":0,"keys":"2","properties":{"KEYS":"2","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.250 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:增加积分,订单id:2
22:03:43.252 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:3,hashCode:51,size:4,index:3,messageQueues:{"body":"5Yib5bu66K6i5Y2V77yM6K6i5Y2VaWTvvJoz","delayTimeLevel":0,"flag":0,"keys":"3","properties":{"KEYS":"3","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.253 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:创建订单,订单id:3
22:03:43.256 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:3,hashCode:51,size:4,index:3,messageQueues:{"body":"5omj5YeP5bqT5a2Y77yM6K6i5Y2VaWTvvJoz","delayTimeLevel":0,"flag":0,"keys":"3","properties":{"KEYS":"3","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.256 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:扣减库存,订单id:3
22:03:43.259 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:3,hashCode:51,size:4,index:3,messageQueues:{"body":"5aKe5Yqg56ev5YiG77yM6K6i5Y2VaWTvvJoz","delayTimeLevel":0,"flag":0,"keys":"3","properties":{"KEYS":"3","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.259 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:增加积分,订单id:3
22:03:43.262 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:4,hashCode:52,size:4,index:0,messageQueues:{"body":"5Yib5bu66K6i5Y2V77yM6K6i5Y2VaWTvvJo0","delayTimeLevel":0,"flag":0,"keys":"4","properties":{"KEYS":"4","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.262 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:创建订单,订单id:4
22:03:43.266 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:4,hashCode:52,size:4,index:0,messageQueues:{"body":"5omj5YeP5bqT5a2Y77yM6K6i5Y2VaWTvvJo0","delayTimeLevel":0,"flag":0,"keys":"4","properties":{"KEYS":"4","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.266 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:扣减库存,订单id:4
22:03:43.269 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:4,hashCode:52,size:4,index:0,messageQueues:{"body":"5aKe5Yqg56ev5YiG77yM6K6i5Y2VaWTvvJo0","delayTimeLevel":0,"flag":0,"keys":"4","properties":{"KEYS":"4","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.270 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:增加积分,订单id:4
22:03:43.272 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:5,hashCode:53,size:4,index:1,messageQueues:{"body":"5Yib5bu66K6i5Y2V77yM6K6i5Y2VaWTvvJo1","delayTimeLevel":0,"flag":0,"keys":"5","properties":{"KEYS":"5","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.273 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:创建订单,订单id:5
22:03:43.275 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:5,hashCode:53,size:4,index:1,messageQueues:{"body":"5omj5YeP5bqT5a2Y77yM6K6i5Y2VaWTvvJo1","delayTimeLevel":0,"flag":0,"keys":"5","properties":{"KEYS":"5","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.275 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:扣减库存,订单id:5
22:03:43.277 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:5,hashCode:53,size:4,index:1,messageQueues:{"body":"5aKe5Yqg56ev5YiG77yM6K6i5Y2VaWTvvJo1","delayTimeLevel":0,"flag":0,"keys":"5","properties":{"KEYS":"5","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.277 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:增加积分,订单id:5
22:03:43.280 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:6,hashCode:54,size:4,index:2,messageQueues:{"body":"5Yib5bu66K6i5Y2V77yM6K6i5Y2VaWTvvJo2","delayTimeLevel":0,"flag":0,"keys":"6","properties":{"KEYS":"6","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.280 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:创建订单,订单id:6
22:03:43.284 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:6,hashCode:54,size:4,index:2,messageQueues:{"body":"5omj5YeP5bqT5a2Y77yM6K6i5Y2VaWTvvJo2","delayTimeLevel":0,"flag":0,"keys":"6","properties":{"KEYS":"6","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.284 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:扣减库存,订单id:6
22:03:43.288 [main] INFO org.star.orderly.producer.DLJDOrderProducer - keys:6,hashCode:54,size:4,index:2,messageQueues:{"body":"5aKe5Yqg56ev5YiG77yM6K6i5Y2VaWTvvJo2","delayTimeLevel":0,"flag":0,"keys":"6","properties":{"KEYS":"6","WAIT":"true","TAGS":"DLJDOrderTag"},"tags":"DLJDOrderTag","topic":"DLJDOrderTopic","waitStoreMsgOK":true}
22:03:43.288 [main] INFO org.star.orderly.producer.DLJDOrderProducer - 当前操作:增加积分,订单id:6
22:03:43.291 [main] INFO org.star.orderly.producer.DLJDOrderProducer - DLJDOrderProducer start success


# 消费者1
22:03:43.237 [ConsumeMessageThread_12] INFO org.star.orderly.consumer.DLJDOrderConsumer1 - 我是消费者DLJDOrderConsumer1,当前线程:ConsumeMessageThread_12,队列ID:1,收到消息:创建订单,订单id:1
22:03:43.240 [ConsumeMessageThread_13] INFO org.star.orderly.consumer.DLJDOrderConsumer1 - 我是消费者DLJDOrderConsumer1,当前线程:ConsumeMessageThread_13,队列ID:1,收到消息:扣减库存,订单id:1
22:03:43.245 [ConsumeMessageThread_14] INFO org.star.orderly.consumer.DLJDOrderConsumer1 - 我是消费者DLJDOrderConsumer1,当前线程:ConsumeMessageThread_14,队列ID:1,收到消息:增加积分,订单id:1
22:03:43.266 [ConsumeMessageThread_15] INFO org.star.orderly.consumer.DLJDOrderConsumer1 - 我是消费者DLJDOrderConsumer1,当前线程:ConsumeMessageThread_15,队列ID:0,收到消息:创建订单,订单id:4
22:03:43.271 [ConsumeMessageThread_16] INFO org.star.orderly.consumer.DLJDOrderConsumer1 - 我是消费者DLJDOrderConsumer1,当前线程:ConsumeMessageThread_16,队列ID:0,收到消息:扣减库存,订单id:4
22:03:43.273 [ConsumeMessageThread_17] INFO org.star.orderly.consumer.DLJDOrderConsumer1 - 我是消费者DLJDOrderConsumer1,当前线程:ConsumeMessageThread_17,队列ID:0,收到消息:增加积分,订单id:4
22:03:43.277 [ConsumeMessageThread_18] INFO org.star.orderly.consumer.DLJDOrderConsumer1 - 我是消费者DLJDOrderConsumer1,当前线程:ConsumeMessageThread_18,队列ID:1,收到消息:创建订单,订单id:5
22:03:43.279 [ConsumeMessageThread_19] INFO org.star.orderly.consumer.DLJDOrderConsumer1 - 我是消费者DLJDOrderConsumer1,当前线程:ConsumeMessageThread_19,队列ID:1,收到消息:扣减库存,订单id:5
22:03:43.281 [ConsumeMessageThread_20] INFO org.star.orderly.consumer.DLJDOrderConsumer1 - 我是消费者DLJDOrderConsumer1,当前线程:ConsumeMessageThread_20,队列ID:1,收到消息:增加积分,订单id:5

# 消费者2
22:03:43.272 [ConsumeMessageThread_2] INFO org.star.orderly.consumer.DLJDOrderConsumer2 - 我是消费者DLJDOrderConsumer2,当前线程:ConsumeMessageThread_2,队列ID:3,收到消息:创建订单,订单id:3
22:03:43.272 [ConsumeMessageThread_1] INFO org.star.orderly.consumer.DLJDOrderConsumer2 - 我是消费者DLJDOrderConsumer2,当前线程:ConsumeMessageThread_1,队列ID:2,收到消息:创建订单,订单id:2
22:03:43.275 [ConsumeMessageThread_1] INFO org.star.orderly.consumer.DLJDOrderConsumer2 - 我是消费者DLJDOrderConsumer2,当前线程:ConsumeMessageThread_1,队列ID:2,收到消息:扣减库存,订单id:2
22:03:43.275 [ConsumeMessageThread_2] INFO org.star.orderly.consumer.DLJDOrderConsumer2 - 我是消费者DLJDOrderConsumer2,当前线程:ConsumeMessageThread_2,队列ID:3,收到消息:扣减库存,订单id:3
22:03:43.275 [ConsumeMessageThread_1] INFO org.star.orderly.consumer.DLJDOrderConsumer2 - 我是消费者DLJDOrderConsumer2,当前线程:ConsumeMessageThread_1,队列ID:2,收到消息:增加积分,订单id:2
22:03:43.275 [ConsumeMessageThread_2] INFO org.star.orderly.consumer.DLJDOrderConsumer2 - 我是消费者DLJDOrderConsumer2,当前线程:ConsumeMessageThread_2,队列ID:3,收到消息:增加积分,订单id:3
22:03:43.287 [ConsumeMessageThread_3] INFO org.star.orderly.consumer.DLJDOrderConsumer2 - 我是消费者DLJDOrderConsumer2,当前线程:ConsumeMessageThread_3,队列ID:2,收到消息:创建订单,订单id:6
22:03:43.299 [ConsumeMessageThread_4] INFO org.star.orderly.consumer.DLJDOrderConsumer2 - 我是消费者DLJDOrderConsumer2,当前线程:ConsumeMessageThread_4,队列ID:2,收到消息:扣减库存,订单id:6
22:03:43.303 [ConsumeMessageThread_5] INFO org.star.orderly.consumer.DLJDOrderConsumer2 - 我是消费者DLJDOrderConsumer2,当前线程:ConsumeMessageThread_5,队列ID:2,收到消息:增加积分,订单id:6

你可能感兴趣的:(RocketMQ系列,java-rocketmq,java,rocketmq)