RocketMQ 如何保证消息的有序性?
1 有序消息的基本概念
有序消息又叫顺序消息(FIFO 消息) 是指消息的消费顺序和产生顺序相同,在有些业务逻辑下,必须保证顺序。
比如设备的上线、事件上报、下线,这个消息必须按顺序处理才行。 这边顺序消息分为全局顺序和分区(queue)顺序。
1.1 全局顺序
概念
一个Topic内所有的消息都发布到同一个queue,按照先进先出的顺序进行发布和消费
适用场景
性能要求不高,所有的消息严格按照FIFO原则进行消息发布和消费的场景
2.2 分区顺序
概念
对于指定的一个Topic,所有消息根据sharding key进行(queue)分区推送
同一个queue内的消息按照严格的FIFO顺序进行发布和消费
Sharding key是顺序消息中用来区分不同分区的关键字段,和普通消息的 Key是完全不同的概念
适用场景
性能要求高,根据消息中的sharding key去决定消息发送到哪个queue
2.3 全局顺序与分区顺序对比
2 如何保证消息顺序
在MQ的模型中,顺序需要由3个阶段去保障
- 消息被发送时保持顺序
- 消息被存储时保持和发送的顺序一致
- 消息被消费时保持和存储的顺序一致
3 RocketMQ 的有序消息实现原理
RocketMQ消费端有两种类型:
- MQPullConsumer
- MQPushConsumer
底层都是通过pull机制去实现,pushConsumer是一种API封装
MQPullConsumer
由用户控制线程,主动从服务端获取消息,每次获取到的是一个MessageQueue
中的消息。
PullResult
中的 List<MessageExt> msgFoundList
自然和存储顺序一致,用户需要再拿到这批消息后自己保证消费的顺序。
MQPushConsumer
由用户注册MessageListener
来消费消息,在客户端中需要保证调用MessageListener
时消息的顺序性
- 拉取生产端消息
- 判断是并发的还是有序的,对应不同服务实现类
4 有序消息的缺陷
发送顺序消息无法利用集群的Failover特性,因为不能更换MessageQueue进行重试。