使用 RocketMQ ,如何保证消息顺序

参考答案

这是一道最常见、高频的 RocketMQ  面试题,需要我们对 MQ 场景有一定的深入理解。

下面详解:

1   为什么要保证消息有序?(在什么场景中要保证消息有序?)

假设:

我们有个大数据系统,需要对业务系统的日志进行收集分析,为了减少对业务系统的影响,通常都会通过 MQ 来做消息中转。此时,对消息的顺序就有一定的要求。

我们可以考虑下面这一系列的操作:

  • 用户的积分默认是0分,而新注册用户设置为默认的10分。
  • 用户有奖励行为,积分+2分。
  • 用户有不正当行为,积分-3分。

这样一组操作,正常用户积分要变成9分。

但是,如果顺序乱了,结果就全部不对了。这个时候,就需要对这一组操作,保证消息都是有序的。

那么,如何保证消息都是有序的呢?

2    如何保证消息有序?

MQ 的顺序问题分为全局有序局部有序

  • 全局有序:整个MQ系统的所有消息严格按照队列先入先出顺序进行消费。
  • 局部有序:只保证一部分关键消息的消费顺序。

在通常的业务场景中,全局有序和局部有序哪个更重要呢?

在大部分的 MQ 业务场景中,我们只需要能够保证局部有序就行了。

例如,

  • 我们用QQ聊天,只需要保证一个聊天窗口里的消息有序就可以了。
  • 对于电商订单场景,也只要保证一个订单的所有消息是有序的就可以了。

至于全局消息的顺序,并不会太关心。通常,全局有序都可以压缩成局部有序。

例如:

以前我们常用的聊天室,就是个典型的需要保证消息全局有序的场景。

但是,这种场景通常可以压缩成只有一个聊天窗口的 QQ 。即:整个系统只有一个聊天通道,用 QQ 那种保证一个聊天窗口消息有序的方式,来保证整个系统的全局消息有序,再落地到RocketMQ。

通常情况下,发送者发送消息时,会通过 MessageQueue 轮询的方式,保证消息尽量均匀的分布到所有的 MessageQueue 上,消费者同样需要从多个 MessageQueue 上消费消息, MessageQueue 是 RocketMQ 存储消息的最小单元,他们之间的消息都是互相隔离的,在这种情况下,将无法保证消息全局有序。

而对于局部有序的要求,只需要将有序的一组消息都存入同一个 MessageQueue 里,这样MessageQueue 的 FIFO 设计,就能保证这一组消息的有序。

RocketMQ 中,可以在发送者发送消息时指定一个 MessageSelector 对象,让这个对象来决定消息发入哪一个 MessageQueue 。以保证一组有序的消息,能够发到同一个 MessageQueue 里。

另外,通常所谓的保证 Topic 全局消息有序的方式,就是将 Topic 配置成只有一个 MessageQueue 队列(默认是4个),这样就能保证消息全局有序了。

其实,就是将聊天室场景压缩成只有一个聊天窗口的QQ一样的理解方式。该方式对整个 Topic 的消息吞吐影响非常大,如果这样用,基本上就没有用 MQ 的必要了。

 

以上,是消息队列 RocketMQ 面试题【使用 RocketMQ ,如何保证消息顺序】的参考答案。

输出,是最好的学习方法

欢迎在评论区留下你的问题、笔记或知识点补充~

—end—

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧