rocketmq_003_顺序消息

消息有序指的是可以按照消息的发送顺序消费(FIFO)。RocketMQ可以严格保证消息有序性,可以分为分区有序或者全局有序。

消费顺序原理:

在默认情况下消息发送采用round robin轮询方式把消息发送到不同的queue,而消费消息时从多个queue上获取消息,这种情况无法保证有序性,但是如果消息只发送到同一个queue中,消费时只从该queue中拉取,就可保证有序。当发送和消费只有一个queue,则全局有序,如果多个queue参与,则为分区有序,即相对每个queue消息都是有序的

下面用订单进行分区有序的实例,一个订单的顺序流程是:创建、付款、推送、完成。订单号相同的消息会被推送到一个queue中,按序被消费

先创建一个订单集合

public class OrderStep {
    private Long orderId;
    private String desc;

    public OrderStep(){}

    public OrderStep(Long orderId, String desc) {
        this.orderId = orderId;
        this.desc = 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 + '\'' +
                '}';
    }

    public static List<OrderStep> buildOrders(){
        List<OrderStep> orderSteps = new ArrayList<>();
        orderSteps.add(new OrderStep(00001L,"创建"));
        orderSteps.add(new OrderStep(00001L,"付款"));
        orderSteps.add(new OrderStep(00001L,"消费"));
        orderSteps.add(new OrderStep(00001L,"完成"));
        orderSteps.add(new OrderStep(00002L,"创建"));
        orderSteps.add(new OrderStep(00002L,"付款"));
        orderSteps.add(new OrderStep(00002L,"消费"));
        orderSteps.add(new OrderStep(00002L,"完成"));
        orderSteps.add(new OrderStep(00003L,"创建"));
        orderSteps.add(new OrderStep(00003L,"付款"));
        orderSteps.add(new OrderStep(00003L,"消费"));
        orderSteps.add(new OrderStep(00003L,"完成"));
        orderSteps.add(new OrderStep(00004L,"创建"));
        orderSteps.add(new OrderStep(00004L,"付款"));
        orderSteps.add(new OrderStep(00004L,"消费"));
        orderSteps.add(new OrderStep(00004L,"完成"));
        return orderSteps;
    }
}

消息发送者

public class SyncOrderStepProducer {
    public static void main(String[] args) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
        //        1.创建消息生产者,并且制定生产者组名
        DefaultMQProducer producer = new DefaultMQProducer("group1");
//        设置超时时间
        producer.setSendMsgTimeout(10000);
//        2.指定namesrv地址
        producer.setNamesrvAddr("192.168.48.128:9876;192.168.48.137:9876");
//        producer.setNamesrvAddr("47.96.165.93:9876;106.52.131.197:9876");
//        3.启动producer
        try {
            producer.start();
        } catch (
                MQClientException e) {
            e.printStackTrace();
        }

        List<OrderStep> orderStepList = OrderStep.buildOrders();

        for (OrderStep order: orderStepList){
//        4.创建消息对象,指定主题topic,tag和消息体
            Message msg = new Message("orderTopic","order","order"+order.getOrderId(),order.getDesc().getBytes());
//        5.发送消息,参数1:消息对象;参数2:消息队列的选择器;参数3:选择队列的业务标识(orderId)
            SendResult result = producer.send(msg, new MessageQueueSelector() {
                /**
                 *
                 * @param list  消息队列集合
                 * @param message   消息对象
                 * @param o  业务标识
                 * @return
                 */
                @Override
                public MessageQueue select(List<MessageQueue> list, Message message, Object o) {
                    long orderId = (long) o;
                    int index = (int) (orderId%list.size());
                    return list.get(index);
                }
            },order.getOrderId());

            SendStatus status = result.getSendStatus();

            String msgId = result.getMsgId();

            int queueId = result.getMessageQueue().getQueueId();

            System.out.println("send status:"+status+",message ID:"+msgId+",queue:"+queueId+",desc:"+order.getDesc());
        }
//                * 关闭producer
        producer.shutdown();
    }
}

消息消费者

public class OrderStepConsumer {
    public static void main(String[] args) {
        consumer();
    }

    public static void consumer(){
        //        1 创建消费者Consumer ,并确定消费者组名
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
//        2 指定NameServer地址
        consumer.setNamesrvAddr("192.168.48.128:9876;192.168.48.137:9876");
//        consumer.setNamesrvAddr("106.52.131.197:9876;47.96.165.93:9876");
        try {
//            3 订阅主题Topic和Tag
            consumer.subscribe("orderTopic","*");
//        4 设置回调函数,处理消息
            consumer.registerMessageListener(new MessageListenerOrderly() {
                @Override
                public ConsumeOrderlyStatus consumeMessage(List<MessageExt> list, ConsumeOrderlyContext consumeOrderlyContext) {
                    for(MessageExt msg:list){
                        System.out.println(Thread.currentThread().getName()+",消费消息:"+new String(msg.getBody()));
                    }
                    return ConsumeOrderlyStatus.SUCCESS;
                }
            });
//        5 启动消息内容
            consumer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }
    }
}

启动消费者和发送者

发送成功

send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B610000,queue:1,desc:创建
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B710001,queue:1,desc:付款
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B730002,queue:1,desc:消费
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B750003,queue:1,desc:完成
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B790004,queue:2,desc:创建
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B7A0005,queue:2,desc:付款
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B860006,queue:2,desc:消费
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B910007,queue:2,desc:完成
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B950008,queue:3,desc:创建
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B970009,queue:3,desc:付款
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B9D000A,queue:3,desc:消费
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47B9E000B,queue:3,desc:完成
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47BA0000C,queue:0,desc:创建
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47BA9000D,queue:0,desc:付款
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47BAC000E,queue:0,desc:消费
send status:SEND_OK,message ID:C0A800033A0C18B4AAC251E47BAF000F,queue:0,desc:完成

接收成功,消费者开了四个线程,一个线程监听一个队列 

ConsumeMessageThread_3,消费消息:创建
ConsumeMessageThread_4,消费消息:创建
ConsumeMessageThread_1,消费消息:创建
ConsumeMessageThread_2,消费消息:创建
ConsumeMessageThread_4,消费消息:付款
ConsumeMessageThread_3,消费消息:付款
ConsumeMessageThread_4,消费消息:消费
ConsumeMessageThread_2,消费消息:付款
ConsumeMessageThread_4,消费消息:完成
ConsumeMessageThread_1,消费消息:付款
ConsumeMessageThread_2,消费消息:消费
ConsumeMessageThread_3,消费消息:消费
ConsumeMessageThread_1,消费消息:消费
ConsumeMessageThread_2,消费消息:完成
ConsumeMessageThread_1,消费消息:完成
ConsumeMessageThread_3,消费消息:完成

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值