参考答案
这是一道最常见、高频的 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—