消息队列-RockMQ-顺序收发消息实战

顺序收发消息实战

背景:
假如我们有三个任务,任务1ABC,任务2DQ,任务3NQR,ABC这些字母都代表一个业务消息都要按照自己的内部的顺序消费。
1 全局有序
这个时候我们可以往一个队列里面写入数据,也只选择一个消费者进行消费,那么这个时候肯定是由序的。哪怕我们有ABDC 中间穿插了D但是最终还是一致的。可以解决上面我们这个场景,但是这样的解决方案不是最好的,降低了消费效率和吞吐量。
消息队列-RockMQ-顺序收发消息实战_第1张图片

2 局部有序
通过上面的思考我知道其实保证每个任务内部有序就行了,那么如果我们每个任务的消息都路由到同一个队列岂不是就可以了吗?如下面这张图,那么是不是大大的提高了消费的能力呢?
消息队列-RockMQ-顺序收发消息实战_第2张图片
3 代码
启动类,这里开启了两个通道一个通道验证全局有序性,一个通道验证局部有序性。

@SpringBootApplication
@EnableBinding({CustomSink.class})
public class RocketOrderlyApplication {
    public static void main(String[] args) {
        SpringApplication.run(RocketOrderlyApplication.class, args);
    }
    @StreamListener("input")
    public void receiveInput(String receiveMsg) {
        System.out.println("input receive: " + receiveMsg);
    }
    @StreamListener("input2")
    public void receiveInputSecond(String receiveMsg) {
        System.out.println("input2 receive: " + receiveMsg);
    }
}

配置

server:
  port: 9520
spring:
  application:
    name: rocket-orderly
  cloud:
    stream:
      bindings:
        input:
          content-type: application/json
          destination: GLOBAL_ORDER_TOPIC
          group: test-group-order
        input2:
          content-type: application/json
          destination: PART_ORDER_TOPIC
          group: test-order
      rocketmq:
        bindings:
          input:
            consumer:
              orderly : true #配置是否有序
        binder:
          name-server: ip:9876
          group: rocket-demo

下面来看全局有序性的生产者

public static void main(String[] args) throws Exception {
      DefaultMQProducer producer = new DefaultMQProducer("producer_group");
      producer.setNamesrvAddr("ip:9876");
      producer.start();
      List<Order> F = OrderBuilder.build(1, "A", "B", "C");
      List<Order> S = OrderBuilder.build(2, "D", "Q");
      List<Order> T = OrderBuilder.build(3, "N", "Q", "R");
      ArrayList<Order> orders = new ArrayList<Order>() {{
          addAll(F);
          addAll(S);
          addAll(T);
      }};
      for (Order order : orders) {
          Message msg = new Message("GLOBAL_ORDER_TOPIC", "GLOBAL_ORDER_TOPIC_STR", order.toString().getBytes());
          msg.setKeys("GLOBAL_ORDER_TOPIC_TRACE");
          producer.send(msg);
      }
  }

消息队列-RockMQ-顺序收发消息实战_第3张图片
下面来看局部有序性的生产者

public class Producer2 {
    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("producer_group");
        producer.setNamesrvAddr("ip:9876");
        producer.start();
        List<Order> F = OrderBuilder.build(1, "A", "B", "C");
        List<Order> S = OrderBuilder.build(2, "D", "Q");
        List<Order> T = OrderBuilder.build(3, "N", "Q", "R");
        ArrayList<Order> orders = new ArrayList<Order>() {{
            addAll(F);
            addAll(S);
            addAll(T);
        }};

        for (Order order : orders) {
            Message msg = new Message("PART_ORDER_TOPIC", "PART_ORDER_TOPIC_STR", order.toString().getBytes());
            msg.setKeys("PART_ORDER_TOPIC_TRACE");
            producer.send(msg, new MessageQueueSelector() {
                @Override
                public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                	// 重要的逻辑在这里,这里通过取余的方式将同一个任务的ID路由到同一个队列
                    int size = mqs.size();
                    int idx = (int) arg;
                    return mqs.get(idx % size);
                }
            }, order.getOrderID());
        }
    }
}

我们启动了四个消费者去消费消息得到如下结果,课件保证了局部有序性:
在这里插入图片描述

你可能感兴趣的:(消息队列,消息队列,rocketmq,顺序收发)