RocketMQ-顺序消息Demo及实现原理分析

场景分析

顺序消费是指消息的产生顺序和消费顺序相同

假设有个下单场景,每个阶段需要发邮件通知用户订单状态变化。用户付款完成时系统给用户发送订单已付款邮件,订单已发货时给用户发送订单已发货邮件,订单完成时给用户发送订单已完成邮件。

发送邮件的操作为了不阻塞订单主流程,可以通过mq消息来解耦,下游邮件服务器收到mq消息后发送具体邮件,已付款邮件、已发货邮件、订单已完成邮件这三个消息,下游的邮件服务器需要顺序消费这3个消息并且顺序发送邮件才有意义。否则就会出现已发货邮件先发出,已付款邮件后发出的情况。

但是mq消费者往往是集群部署,一个消费组内存在多个消费者,同一个消费者内部,也可能存在多个消费线程并行消费,如何在消费者集群环境中,如何保证邮件mq消息发送与消费的顺序性呢?

顺序消费又分两种,全局顺序消费和局部顺序消费

全局顺序消费

什么是全局顺序消费?所有发到mq的消息都被顺序消费,类似数据库中的binlog,需要严格保证全局操作的顺序性

那么RocketMQ中如何做才能保证全局顺序消费呢?

这就需要设置topic下读写队列数量为1

为什么要设置读写队列数量为1呢?
假设读写队列有多个,消息就会存储在多个队列中,消费者负载时可能会分配到多个消费队列同时进行消费,多队列并发消费时,无法保证消息消费顺序性

那么全局顺序消费有必要么?
A、B都下了单,B用户订单的邮件先发送,A的后发送,不行么?其实,大多数场景下,mq下只需要保证局部消息顺序即可,即A的付款消息先于A的发货消息即可,A的消息和B的消息可以打乱,这样系统的吞吐量会更好,将队列数量置为1,极大的降低了系统的吞吐量,不符合mq的设计初衷

举个例子来说明局部顺序消费。假设订单A的消息为A1,A2,A3,发送顺序也如此。订单B的消息为B1,B2,B3,A订单消息先发送,B订单消息后发送

消费顺序如下
A1,A2,A3,B1,B2,B3是全局顺序消息,严重降低了系统的并发度
A1,B1,A2,A3,B2,B3是局部顺序消息,可以被接受
A2,B1,A1,B2,A3,B3不可接收,因为A2出现在了A1的前面

局部顺序消费

那么在RocketMQ里局部顺序消息又是如何怎么实现的呢?

要保证消息的顺序消费,有三个关键点

  1. 消息顺序发送
  2. 消息顺序存储
  3. 消息顺序消费

第一点,消息顺序发送,多线程发送的消息无法保证有序性,因此,需要业务方在发送时,针对同一个业务编号(如同一笔订单)的消息需要保证在一个线程内顺序发送,在上一个消息发送成功后,在进行下一个消息的发送。对应到mq中,消息发送方法就得使用同步发送,异步发送无法保证顺序性

第二点,消息顺序存储,mq的topic下会存在多个queue,要保证消息的顺序存储,同一个业务编号的消息需要被发送到一个queue中。对应到mq中,需要使用MessageQueueSelector来选择要发送的queue,即对业务编号进行hash,然后根据队列数量对hash值取余,将消息发送到一个queue中

第三点,消息顺序消费,要保证消息顺序消费,同一个queue就只能被一个消费者所消费,因此对broker中消费队列加锁是无法避免的。同一时刻,一个消费队列只能被一个消费者消费,消费者内部,也只能有一个消费线程来消费该队列。即,同一时刻,一个消费队列只能被一个消费者中的一个线程消费

上面第一、第二点中提到,要保证消息顺序发送和消息顺序存储需要使用mq的同步发送和MessageQueueSelector来保证,具体Demo会有体现

至于第三点中的加锁操作会结合源码来具体分析

Demo

producer中模拟了两个线程,并发顺序发送100个消息的情况,发送的消息中,key为消息发送编号i,消息body为orderId,大家注意下MessageQueueSelector的使用

consumer的demo有两个,第一个为正常集群消费的consumer,另外一个是顺序消费的consumer,从结果中观察消息消费顺序

理想情况下消息顺序消费的结果应该是,同一个orderId下的消息的编号i值应该顺序递增,但是不同orderId之间的消费可以并行,即局部有序即可

Producer Demo

public class Producer {
    public static void main(String[] args)  {
        try {
            MQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
            ((DefaultMQProducer) producer).setNamesrvAddr("1
  • 38
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值