顺序消费的使用场景是某些业务必须同步完成的时候可以使用
看一下官网的解释
其实很好理解
就是这一个业务线的数据都发到同一个queue中并且使用同一个消费者来消费,这样相对于每个queue就是有序的
把官网的代码写了一遍理解了一下
生产者代码意思就是使用设定的规则让这系列的业务消息都发送到在一个队列中
package com.qiqi.mq;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Created By 丛梓祺 on 2021/9/27
* Write this code and change the world
*/
public class ProducerTest {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("default_producer");
producer.setNamesrvAddr("60.205.0.29:9876");
//设置三个标签
String[] tags = new String[]{"TagA", "TagC", "TagD"};
List<OrderStep> orderSteps = new ProducerTest().buildOrders();
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String datestr = simpleDateFormat.format(date);
producer.start();
for (int i = 0; i < 10; i++) {
String body = datestr + "czq rocketmq" + orderSteps.get(i);
//tags[i % 3]标识消息的标签,消费者在消费的时候,可以根据标签进行过滤
Message message = new Message("syncTest", "tags", "KEY" + i, body.getBytes());
//new MessageQueueSelector表示根据
//args回调orderSteps.get(i).orderId这个参数
SendResult sendResult = producer.send(message, new MessageQueueSelector() {
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
Long id = (Long) arg;
long index = id % mqs.size();
return mqs.get((int) index);
}
}, orderSteps.get(i).orderId);
System.out.println(String.format("SendResult status:%s, queueId:%d, body:%s",
sendResult.getSendStatus(),
sendResult.getMessageQueue().getQueueId(),
body));
}
producer.shutdown();
}
private static class OrderStep {
private long orderId;
private String desc;
public long getOrderId() {
return orderId;
}
public void setOrderId(long orderId) {
this.orderId = orderId;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "OrderStep{" +
"orderId=" + orderId +
", desc='" + desc + '\'' +
'}';
}
}
/**
* 生成模拟订单数据
*/
private List<OrderStep> buildOrders() {
List<OrderStep> orderList = new ArrayList<OrderStep>();
OrderStep orderDemo = new OrderStep();
orderDemo.setOrderId(15103111039L);
orderDemo.setDesc("创建");
orderList.add(orderDemo);
orderDemo = new OrderStep();
orderDemo.setOrderId(15103111065L);
orderDemo.setDesc("创建");
orderList.add(orderDemo);
orderDemo = new OrderStep();
orderDemo.setOrderId(15103111039L);
orderDemo.setDesc("付款");
orderList.add(orderDemo);
orderDemo = new OrderStep();
orderDemo.setOrderId(15103117235L);
orderDemo.setDesc("创建");
orderList.add(orderDemo);
orderDemo = new OrderStep();
orderDemo.setOrderId(15103111065L);
orderDemo.setDesc("付款");
orderList.add(orderDemo);
orderDemo = new OrderStep();
orderDemo.setOrderId(15103117235L);
orderDemo.setDesc("付款");
orderList.add(orderDemo);
orderDemo = new OrderStep();
orderDemo.setOrderId(15103111065L);
orderDemo.setDesc("完成");
orderList.add(orderDemo);
orderDemo = new OrderStep();
orderDemo.setOrderId(15103111039L);
orderDemo.setDesc("推送");
orderList.add(orderDemo);
orderDemo = new OrderStep();
orderDemo.setOrderId(15103117235L);
orderDemo.setDesc("完成");
orderList.add(orderDemo);
orderDemo = new OrderStep();
orderDemo.setOrderId(15103111039L);
orderDemo.setDesc("完成");
orderList.add(orderDemo);
return orderList;
}
}
package com.qiqi.mq;
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.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* Created By 丛梓祺 on 2021/9/27
* Write this code and change the world
*/
public class ConsumerTest {
public static void main(String[] args) throws Exception {
final DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("push_test_sync");
consumer.setNamesrvAddr("60.205.0.29:9876");
consumer.subscribe("syncTest", "TagA || TagC || TagD");
//表示consumer从队列的什么位置进行消费
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
//使用这个方法应该就是保证每个消费者线程就只能消费这一个队列
consumer.registerMessageListener(new MessageListenerOrderly() {
Random random = new Random();
public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {
context.setAutoCommit(true);
for (MessageExt msg : msgs) {
// 可以看到每个queue有唯一的consume线程来消费, 订单对每个queue(分区)有序
System.out.println("consumeThread=" + Thread.currentThread().getName() + "queueId=" + msg.getQueueId() + ", content:" + new String(msg.getBody()));
}
try {
TimeUnit.SECONDS.sleep(random.nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
return ConsumeOrderlyStatus.SUCCESS;
}
});
consumer.start();
System.out.println("Consumer start");
}
}
可以看到虽然消费顺序不是强一致的但是每个线程消费的顺序是一致的,这样就可以保证普通的一致性。
这里面其实message的参数tags不太理解
大概意思就是区分不同类型的消息,可以通过这个类型来消费者区分这些消息的类型和做一些过滤?
看了一下官网的定义发现我还不是很理解 等以后用到的时候再研究 。