RocketMQ源码分析 -- 顺序消费 (顺序消息)

3 篇文章 0 订阅
3 篇文章 0 订阅

目的: 从源码角度解读RocketMQ 是如何保证消息顺序消费的

  •         RocketMQ 生产者 ---broker---消费者之间的关系如下图

          

           大家看RocketMQ 官方文档应该有了解到,Rocketmq 能保证单个队列的局部有序性,但无法保证全局的有序性。

           如何保证消息有序?我们从两个方面解读: 一首先要保证消息发送方发送消息有序,其次消费方要保证消费消息的顺序性

  •     消息生产者保证消息有序: 上面我们提到,Rocketmq 可以保证单个队列的有序性,所以消息生产者需要保证相同类型的消息投递到同一个队列中,Rocketmq 提供了几种消息路由策略

           首先看看Rocketmq的消息发送类:MQProducer.java, 里面有个很关键的参数是MessageQueueSelector,这个主要用来做消息的队列路由。

           

            MessageQueueSelector主要有一下几个实现类 SelectMessageQueueByHash   SelectMessageQueueByMachineRoom  SelectMessageQueueByRandom

             

             SelectMessageQueueByHash: 这个对于需要顺序消息来说非常重要,我们可以根据业务唯一性ID 来进行hash路由,比如对于订单类业务,

              我们可以根据订单ID进行hash 路由,进而保证相同的订单可以发送到相同的队列。 

             SelectMessageQueueByMachineRoom: 这个对于多机房的场景比较实用,相同机房的业务把消息发送相同机房的MQ集群,减少跨机房的数据传输

             SelectMessageQueueByRandom: 随机发送从字面意思也很好理解了,就是随机找到一个队列进行发送。无法保障消息的有序性。

     

            提示:  很多人会问一个问题,比如有message A和message B,  预期的结果是A先消费B后消费。  我们在消息发送的时候业务必须保证,消息A发送成功后再发送消息B,否则无法保证消息的有序性。

 

  •     消息消费者保证消息有序

           ConsumeMessageService是Rocketmq 客户端消费消息的接口类,他主要有两个实现类ConsumeMessageOrderlyService 和ConsumeMessageConcurrentlyService

            

          ConsumeMessageConcurrentlyService :并发消费,客户端批量从broker拉取到消息后会提交到线程池去执行。

             

         ConsumeMessageOrderlyService: 顺序消费,消息处理之前,首先对消息暂存的队列加锁,保证只有一个线程顺序消费

       (反过来想一下,如果我们使用多线程,即便我们从broker拉取的消息是有序的,但是由于两个消息同时提交到两个线程去执行,因为CPU的时间片是无序的,无法保证执行的先后,也就很难做到业务上的消息顺序)

         

 

      综上: 如果我们想保证消息的有序性,消息生产者和消息消费者必须两手抓,并且两手都要硬

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值