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